lua – 在迭代时从数组表中安全地删除项目

前端之家收集整理的这篇文章主要介绍了lua – 在迭代时从数组表中安全地删除项目前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这个问题与 How can I safely iterate a lua table while keys are being removed类似,但明显不同。

概要

给定一个Lua数组(具有从1开始的顺序整数的键的表),迭代这个数组并删除一些条目的最佳方式是什么?

现实世界的例子

我在Lua数组表中有一个timestamped条目数组。条目总是添加到数组的末尾(使用table.insert)。

local timestampedEvents = {}
function addEvent( data )
  table.insert( timestampedEvents,{getCurrentTime(),data} )
end

我需要偶尔运行这个表(按顺序),并处理和删除某些条目:

function processEventsBefore( timestamp )
  for i,stamp in ipairs( timestampedEvents ) do
    if stamp[1] <= timestamp then
      processEventData( stamp[2] )
      table.remove( timestampedEvents,i )
    end
  end
end

不幸的是,上面的代码打破了迭代,跳过了一些条目。有没有比手动走索引更好(更少打字,但仍然安全)这样做

function processEventsBefore( timestamp )
  local i = 1
  while i <= #timestampedEvents do -- warning: do not cache the table length
    local stamp = timestampedEvents[i]
    if stamp[1] <= timestamp then
      processEventData( stamp[2] )
      table.remove( timestampedEvents,i )
    else
      i = i + 1
    end
  end
end

解决方法

the general case of iterating over an array and removing random items from the middle while continuing to iterate

只需使用table.remove。但是,如果您从头到尾迭代,则当您删除元素N时,迭代中的下一个元素(N 1)会向下移动到该位置。如果你增加迭代变量(如ipairs),你将跳过该元素。有两种方法可以处理这个问题。

使用此示例数据:

input = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p' }
    remove = { f=true,g=true,j=true,n=true,o=true,p=true }

我们可以通过以下方式在迭代中删除输入元素

>从后面到前面迭代

for i=#input,1,-1 do
    if remove[input[i]] then
        table.remove(input,i)
    end
end

>手动控制循环变量,所以我们可以在删除元素时跳过它:

local i=1
while i <= #input do
    if remove[input[i]] then
        table.remove(input,i)
    else
        i = i + 1
    end
end

对于非数组表,您可以使用下一个或多个对(以下一个方式实现)迭代,并将要删除的项设置为零。

猜你在找的Lua相关文章