动态表或阵列(dynamic tables or arrays)

2019-10-29 12:17发布

我有一个,就是动态改变三维数组或表的大小的功能,但它一直破说,它的返回值为零,因为它是出界。 下面是它的代码:

function resize()       
    temp = { }
    for h=1, height do
        table.insert( temp , { } )
        for y=1, length do
            table.insert ( temp[h], { } )
            for x=1, width do
                num = 16                
                if #blocks <= height then
                    if #blocks[h] <= length then
                        if #blocks[h][y] <= width then
                            num = blocks[h][y][x]
                        end
                    end
                end         
                table.insert( temp[h][y] , num )
            end
        end
    end 
    blocks = temp
end

我知道这不是很好的评论,但这个想法是,它创建与修改尺寸的新表,然后叠加在新表块与新的临时表中的数据,并最终覆盖块。

长度的宽度和高度由一个或者递增变化或递减,但只有一个在一个时间。

我不知道如果我解释清楚就够了,如果不是让我知道,我会尽力解释更多的细节。

感谢所有,詹姆斯

Answer 1:

我认为,错误在于你的if语句。 你应该针对H块,y和x,而不是高度和长度和宽度的尺寸。

作为一个侧面说明,不使用时table.insert你可以用临时[H +] = {}代替它。 它的速度更快。 另外,尽量用当地人的临时存储。



Answer 2:

您的特定错误(可能)

你不测试对零值。 任何非初始化表(=在这种情况下阵列)成员都是nil定义。 而比较nil以数将产生一个错误:

lua: attempt to compare nil with number

但是,你似乎无法提供实际的错误信息,这只是一种猜测。 不要把我错了,这些都是在你的代码中的错误,但也有可能是别的东西错了,我忽略了。 反正这里是你的代码以及一些评论给你看会发生什么

if #blocks <= height then              -- say #blocks is 3, height is 4
    if #blocks[h] <= length then       -- E: in iteration 4 blocks[h] is nil
        if #blocks[h][y] <= width then -- E: in it. 3,4 blocks[h][y] is nil
            num = blocks[h][y][x]
        end
    end
end

你必须要测试的各个层面无第一,像

if blocks[h] and blocks[h][y] and blocks[h][y][x] and
       #blocks[h]<=height and #blocks[h][y]<=height and #blocks[h][y][x]<=height
    num = blocks[h][y][x]
end

一般的编程错误

blockslengthwidthheight似乎是你的函数的参数,但不是在它的头,所以我想你将它们设置在外部调用函数之前? 这肯定不是好的做法。

tempnum应该声明local

替代

可以使数据结构更智能,例如,如果你把你的3D阵列中的扁平表并添加一个__call元方法是这样

function newMdArray(X, Y, Z)
    local MT = { __call = function(t, x, y, z, v)
        if x>X or y>Y or z>Z or x<1 or y<1 or z<1 then return nil end
        local k = x + X*(y-1) + X*Y*(z-1);
        if v ~= nil then t[k] = v; end
        return t[k]
    end };
    return setmetatable({}, MT);
end

那么这是你必须做的,做它的一个调整副本:

function resizeMdArray(array, X, Y, Z)
    local r = newMdArray(X, Y, Z);
    for x=1, X do
        for y=1, Y do
            for z=1, Z do
                r(x, y, z, array(x, y, z) or 16);
            end
        end
    end
    return r;
end

一个不错的奖金,由于这个数据结构平展3D阵列分为一维数组,如果你只是想复制的数据,你可以通过简单地访问它为表和复制的每个元素这样做:

for i=1, X*Y*Z do
    new[i] = old[i]
end

当然,你可以做同样的一个“真实”(隐藏)3-D在后台保存您的算术计算阵列,但是,那么你就必须测试空值要防止零错误的时间。



Answer 3:

嗯,我不知道这是否是做的最好的方式,但它确实工作。

function resize()       
temp = { } -- temp table

-- inserting all the height levels
for h=1, height do table.insert( temp , { } ) end

-- inserting all the lengths
for h=1, height do
    for l=1, length do table.insert( temp[h], { } ) end
end

-- inserting all the width and defaulting them to 0
for h=1, height do
    for l=1, length do
        for w=1, width do table.insert( temp[h][l] , 0 ) end
    end
end

-- if the canvas size is increasing
if #blocks <= height then
    if #blocks[1] <= length then
        if #blocks[1][1] <= width then
            for h=1, #blocks do
                for l=1, #blocks[1] do
                    for w=1, #blocks[1][1] do
                        -- fill in data from blocks
                        temp[h][l][w] = blocks[h][l][w]
                    end
                end
            end
        end
    end
end

--if the canvas size is decreasing
if #blocks >= height then
    if #blocks[1] >= length then
        if #blocks[1][1] >= width then
            for h=1, #temp do
                for l=1, #temp[1] do
                    for w=1, #temp[1][1] do
                        -- fill in data from blocks but not the last value
                        temp[h][l][w] = blocks[h][l][w]
                    end
                end
            end
        end
    end
end

-- overwrite blocks with the new dimensions
blocks = temp


文章来源: dynamic tables or arrays