如何获取Lua中的table的最新x个条目?
How to get the latest x entries of a table in Lua?
如果我有 (例如) 一个 table 有 300 个条目,我怎样才能只得到最新的 x 个条目?
我正在考虑做下一步,但我想知道是否有 better/more 优化的方法来做这件事。
local TestTable = {}
-- Populate table
for i = 1, 300, 1 do
print('Adding: ' .. i)
table.insert(TestTable , i)
end
-- Get latest x of table
function GetLatestFromTable(OriginalTable, Amount)
local TableLength = #OriginalTable
local Retval = {}
for i = 1, Amount, 1 do
if TableLength - i <= 0 then break end -- Dont allow to go under 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)
如@Luke100000 所述,一种方法是使用 Lua
自定义迭代器。在 Lua
中,迭代器是一个特殊的函数,当调用它时,它将 return 下一个值。由于函数是 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
是 returning 一个 anonymous function
的函数。匿名函数不接受任何参数。它只是更新在 IterateRange
的局部范围内定义的 ClosureIndex
索引和 return 的 table 值。
匿名函数做的第一件事是增加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
现在,重用这个通用迭代器来迭代给定 table 的 最后 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
这应该return:
290
291
292
293
294
295
296
297
298
299
300
我会让 OP 更新代码,以便为 30
个条目实现相同的结果。
对于序列中的键(值是 string/number)调用 table.concat()
允许范围参数。
local tab = {"One", "Two", "Three", "Four", "Five"}
print(table.concat(tab, '\n', #tab - 1, #tab)) -- Last two entries
如果我有 (例如) 一个 table 有 300 个条目,我怎样才能只得到最新的 x 个条目? 我正在考虑做下一步,但我想知道是否有 better/more 优化的方法来做这件事。
local TestTable = {}
-- Populate table
for i = 1, 300, 1 do
print('Adding: ' .. i)
table.insert(TestTable , i)
end
-- Get latest x of table
function GetLatestFromTable(OriginalTable, Amount)
local TableLength = #OriginalTable
local Retval = {}
for i = 1, Amount, 1 do
if TableLength - i <= 0 then break end -- Dont allow to go under 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)
如@Luke100000 所述,一种方法是使用 Lua
自定义迭代器。在 Lua
中,迭代器是一个特殊的函数,当调用它时,它将 return 下一个值。由于函数是 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
是 returning 一个 anonymous function
的函数。匿名函数不接受任何参数。它只是更新在 IterateRange
的局部范围内定义的 ClosureIndex
索引和 return 的 table 值。
匿名函数做的第一件事是增加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
现在,重用这个通用迭代器来迭代给定 table 的 最后 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
这应该return:
290
291
292
293
294
295
296
297
298
299
300
我会让 OP 更新代码,以便为 30
个条目实现相同的结果。
对于序列中的键(值是 string/number)调用 table.concat()
允许范围参数。
local tab = {"One", "Two", "Three", "Four", "Five"}
print(table.concat(tab, '\n', #tab - 1, #tab)) -- Last two entries