假设我有一张这样的桌子:
{
value = 4
},
{
value = 3
},
{
value = 1
},
{
value = 2
}
我希望迭代它并按顺序打印值,因此输出如下:
1
2
3
4
如何执行此操作,我了解如何使用ipairs
和pairs
以及table.sort
,但只有在使用table.insert并且密钥有效时才能使用,我需要按照值的顺序循环遍历。
我尝试了自定义功能,但它只是以错误的顺序打印出来。
我试过了:
我很好,真的很难过。
答案 0 :(得分:2)
对表格进行排序
这是正确的解决方案。
(抛出错误:尝试在表和表上执行__lt)
听起来你试图使用split(504, 18)
。
为了让Lua能够对值进行排序,它必须知道如何比较它们。它知道如何比较数字和字符串,但默认情况下它知道如何比较两个表。考虑一下:
a < b
如果我打电话给local people = {
{ name = 'fred', age = 43 },
{ name = 'ted', age = 31 },
{ name = 'ned', age = 12 },
}
人,Lua怎么知道我的意图?我不知道'年龄'或'名字'是什么意思,或者我想用它来比较。我必须告诉它。
可以在表格中添加 metatable ,告诉Lua sort
运算符对表的含义,但您也可以为<
提供回调函数告诉它如何比较两个对象。
您向sort
提供一个接收两个值的函数,并使用您对表的了解返回第一个是否小于第二个值。就你的表而言:
sort
答案 1 :(得分:0)
如果您想保持原始表不变,可以创建一个自定义的“按值排序”迭代器,如下所示:
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
-- build new table to sort
local sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
-- sort new table
table.sort( sorted, valueSort );
-- return iterator
return ipairs( sorted );
end
调用sortByValue()
时,它会将tbl
克隆到新的sorted
表,然后对已排序的表进行排序。然后它将sorted
表交给ipairs()
,ipairs
输出要由for
循环使用的迭代器。
使用:
for i,v in sortByValue( myTable ) do
print(v)
end
虽然这可以确保您的原始表保持不变,但它的缺点是,每次进行迭代时,迭代器必须克隆myTable
以创建新的sorted
表,然后{{1}那个table.sort
表。
如果性能至关重要,您可以通过“缓存”sorted
迭代器完成的工作来大大加快速度。更新的代码:
sortByValue()
每次向/ local resort, sorted = true;
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
if not sorted then -- rebuild sorted table
sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
resort = true;
end
if resort then -- sort the 'sorted' table
table.sort( sorted, valueSort );
resort = false;
end
-- return iterator
return ipairs( sorted );
end
设置myTable
添加或删除元素。这让迭代器知道它需要重建sorted = nil
表(并重新排序)。
每次更新其中一个嵌套表中的sorted
属性时,请设置value
。这让迭代器知道它必须做resort = true
。
现在,当您使用迭代器时,它将尝试重新使用缓存的table.sort
表中以前的排序结果。
如果找不到sorted
表(例如,首次使用迭代器,或者因为设置sorted
强制重建),它将重建它。如果它看到它需要求助(例如,在第一次使用时,或者如果sorted = nil
表被重建,或者如果你设置sorted
)那么它将采用resort = true
表。