如何在 Lua 中获取表格的最新 x 项条目?

如果我有一个具有 300 个条目的表格,如何只获取最新的 x 项呢? 我想做下面的事情,但我想知道是否有更好/更优化的方法来完成这个任务。

local TestTable = {}

-- 填充表格
for i = 1, 300, 1 do
    print('Adding: ' .. i)
    table.insert(TestTable , i)
end

-- 获取表格的最新项
function GetLatestFromTable(OriginalTable, Amount)
    local TableLength = #OriginalTable
    local Retval = {}

    for i = 1, Amount, 1 do
        if TableLength - i <= 0 then break end -- 不允许小于 0

        table.insert(Retval, OriginalTable[TableLength - i])

        print("Adding to Retval: " .. OriginalTable[TableLength - i] .. ' (Index: ' .. TableLength - i .. ')')
    end

    return Retval
end

print(#TestTable)
local LatestTable = GetLatestFromTable(TestTable, 10)
print(#LatestTable)

原文链接 https://stackoverflow.com/questions/70316560

点赞
stackoverflow用户10953006
stackoverflow用户10953006

如@Luke100000所述,一种方法是使用Lua自定义迭代器。在Lua中,迭代器是一个特殊的函数,当调用时,它将返回下一个值。这是因为函数在Lua中是_first-class citizen_,它们可以使用名为closure的机制引用先前的作用域而实现的。

要回答问题,可以开始实现一个通用迭代器,该迭代器遍历给定范围。

function IterateRange (Table, Min, Max)

  local ClosureIndex = Min - 1
  local ClosureMax   = math.min(Max, #Table)

  local function Closure ()
    if (ClosureIndex < ClosureMax) then
      ClosureIndex = ClosureIndex + 1
      return Table[ClosureIndex]
    end
  end

  return Closure
end

IterateRange是一个返回匿名函数的函数。匿名函数不接受任何参数。它只是更新IterateRange局部作用域中定义的ClosureIndex索引并返回表中的值。

匿名函数要做的第一件事就是递增ClosureIndex。出于这个原因,ClosureIndex必须初始化为Min - 1

这个函数的工作方式如人们所期望的那样:

TestTable = {}

for i = 1, 300, 1 do
    print('Adding: ' .. i)
    table.insert(TestTable , i)
end

for Value in IterateRange(TestTable, 290, 300) do
  print(Value)
end

290
291
292
293
294
295
296
297
298
299
300

现在,可以轻松地重用这个通用迭代器,以遍历给定表格的_last N条_记录:

function IterateLastEntries (Table, Count)
  local TableSize  = #Table
  local StartIndex = (TableSize - Count)
  return IterateRange(Table, StartIndex, TableSize)
end

它也像人们所期望的那样工作:

TestTable = {}

for i = 1, 300, 1 do
    print('Adding: ' .. i)
    table.insert(TestTable , i)
end

for Value in IterateLastEntries(TestTable, 10) do
  print(Value)
end

290
291
292
293
294
295
296
297
298
299
300

最后,将所有内容汇总在一个完全可复制粘贴的解决方案中:

TestTable = {}

for i = 1, 300, 1 do
    print('Adding: ' .. i)
    table.insert(TestTable , i)
end

function IterateRange (Table, Min, Max)

  local ClosureIndex = Min - 1
  local ClosureMax   = math.min(Max, #Table)

  local function Closure ()
    if (ClosureIndex < ClosureMax) then
      ClosureIndex = ClosureIndex + 1
      return Table[ClosureIndex]
    end
  end

  return Closure
end

function IterateLastEntries (Table, Count)
  local TableSize  = #Table
  local StartIndex = (TableSize - Count)
  return IterateRange(Table, StartIndex, TableSize)
end

for Value in IterateLastEntries(TestTable, 10) do
  print(Value)
end

这应该返回:

290
291
292
293
294
295
296
297
298
299
300

我将让OP更新代码,以便为30个条目实现相同的结果。

2021-12-13 02:34:58
stackoverflow用户11740758
stackoverflow用户11740758

对于序列中的键(且值为字符串/数字),调用table.concat()允许使用范围参数。

local tab = {"One", "Two", "Three", "Four", "Five"}

print(table.concat(tab, '\n', #tab - 1, #tab)) -- 最后两个条目

详见:table.concat()

2021-12-24 12:04:09