【问题标题】:How to remove all 'nil' values from an array?如何从数组中删除所有“零”值?
【发布时间】:2015-04-02 14:47:14
【问题描述】:

我有一个对象数组(或只是数字),我还有另一个数组,其中包含在任何情况下都不应从第一个数组中删除的所有对象。它看起来像这样:

-- Array of objects (just numbers for now)
Objects = {}

-- Array of objects that should always stay in the 'Objects' array
DontDestroyThese = {}

-- Populate the arrays
Objects[#Objects+1] = 1
Objects[#Objects+1] = 2
Objects[#Objects+1] = 3
Objects[#Objects+1] = 4
Objects[#Objects+1] = 5

DontDestroyThese[#DontDestroyThese+1] = 2
DontDestroyThese[#DontDestroyThese+1] = 5

现在,我有一个名为destroy() 的方法,它应该从Objects 数组中删除除DontDestroyThese 数组中包含的对象之外的所有对象。该方法如下所示:

function destroy()
    for I = 1, #Objects do
        if(DontDestroyThese[Objects[I]] ~= nil) then
            print("Skipping " .. Objects[I])
        else
            Objects[I] = nil
        end
    end
end

但是,因此,Objects 数组现在到处都包含nil 值。我想删除这些nils,以便Objects 数组只包含调用destroy() 后留下的数字。我该怎么做?

【问题讨论】:

  • 你试过table.remove(Objects, I)吗?
  • Objects[#Objects] = 1 并没有像你想象的那样做,因为 Lua 中的数组从索引 1 开始。试试Objects[#Objects+1] = 1
  • 我同意@lhf 的评论。 DontDestroyThese[#DontDestroyThese] 也是如此 - 您必须添加 +1
  • 缺少+1 是我在输入代码示例时犯的一个错误。
  • @manabreak 你使用了错误的术语。对象不包含“这里和这里”的 nil。它包含漏洞,因为在 Lua 中将 nil 分配给 table[key] 意味着“删除密钥”。

标签: arrays lua null lua-table


【解决方案1】:

最有效的方法可能是创建一个新表来保存结果。尝试在数组中移动值可能比简单地追加到新表具有更高的开销:

function destroy()
    local tbl = {}
    for I = 1, #Objects do
        if(DontDestroyThese[Objects[I]] ~= nil) then
            table.insert(tbl, Objects[I])
        end
    end
    Objects = tbl
end

此方法还意味着您不必处理更改正在迭代的表/数组的内容。

【讨论】:

  • 谢谢你,不知何故,这些过于简单的解决方案总是让我头疼。 :)
【解决方案2】:

我认为解决方案要简单得多。要删除任何 nils(数组中的“洞”),您需要做的就是使用pairs() 迭代您的表。这将跳过仅返回您添加到新本地表中的非零值的任何 nil,该表在“清理”函数的末尾返回。数组(索引为 1..n 的表)将保持相同的顺序。例如:

function CleanNils(t)
  local ans = {}
  for _,v in pairs(t) do
    ans[ #ans+1 ] = v
  end
  return ans
end

那么你只需要这样做:

Objects = CleanNils(Objects)

测试它:

function show(t)
  for _,v in ipairs(t) do
    print(v)
  end
  print(('='):rep(20))
end

t = {'a','b','c','d','e','f'}
t[4] = nil          --create a 'hole' at 'd'
show(t)             --> a b c
t = CleanNils(t)    --remove the 'hole'
show(t)             --> a b c e f

【讨论】:

    【解决方案3】:
    local function remove(t, pred)
      for i = #t, 1, -1 do
        if pred(t[i], i) then
          table.remove(t, i)
        end
      end
      return t
    end
    
    local function even(v)
      return math.mod(v, 2) == 0
    end
    
    -- remove only even numbers
    local t = remove({1, 2, 3, 4}, even)
    
    -- remove values you want
    local function keep(t)
      return function(v)
        return not t[v]
      end
    end
    
    remove(Objects, keep(DontDestroyThese))
    

    【讨论】:

      猜你喜欢
      • 2019-02-14
      • 2023-03-10
      • 2014-04-01
      • 2012-09-09
      • 1970-01-01
      • 2019-12-09
      • 2015-02-22
      相关资源
      最近更新 更多