为什么我不能使用table.sort对具有关联索引的表进行排序?
答案 0 :(得分:6)
通常,Lua表是纯关联数组。除了作为Lua核心中使用的特定哈希表实现的副作用之外,没有“自然”顺序。这是有道理的,因为任何Lua数据类型的值(nil
除外)都可以用作键和值;但只有字符串和数字有任何合理的排序,然后只在相似类型的值之间。
例如,该表的排序顺序应为:
unsortable = {
answer=42,
true="Beauty",
[function() return 17 end] = function() return 42 end,
[math.pi] = "pi",
[ {} ] = {},
12, 11, 10, 9, 8
}
它有一个字符串键,一个布尔键,一个功能键,一个非整数键,一个表键和五个整数键。该函数应该排在字符串之前吗?你如何比较字符串和数字?表格应该放在哪里?那个userdata
和thread
值不会出现在这个表中呢?
按照惯例,以1开头的连续整数索引的值通常用作列表。几个函数和常用习语遵循此约定,table.sort
就是一个例子。在列表上运行的函数通常会忽略存储在不属于列表的键的任何值。同样,table.sort
是一个示例:它仅对存储在列表中的键中的那些元素进行排序。
另一个例子是#
运算符。对于上表,#unsortable
为5,因为unsortable[5] ~= nil
和unsortable[6] == nil
。请注意,即使pi介于3和4之间,也不会计算存储在数字索引math.pi
中的值,因为它不是整数。此外,也不计算其他非整数键。这意味着一个简单的for循环可以迭代整个列表:
for i in 1,#unsortable do
print(i,unsortable[i])
end
虽然这通常写成
for i,v in ipairs(unsortable) do
print(i,v)
end
简而言之,Lua表是无序的值集合,每个值都由一个键索引;但是从1开始,顺序整数键有一个特殊的约定。
编辑:对于具有合适的部分排序的非整数键的特殊情况,有一个涉及单独索引表的变通方法。所描述的字符串值的表格内容是这个技巧的一个合适的例子。
首先,以列表的形式收集新表中的密钥。也就是说,使用从键开始的连续整数索引表,并将键作为值进行排序。然后,使用该索引以所需顺序迭代原始表。
例如,这里是foreachinorder()
,它使用这种技术迭代表的所有值,按照比较函数确定的顺序为每个键/值对调用一个函数。
function foreachinorder(t, f, cmp)
-- first extract a list of the keys from t
local keys = {}
for k,_ in pairs(t) do
keys[#keys+1] = k
end
-- sort the keys according to the function cmp. If cmp
-- is omitted, table.sort() defaults to the < operator
table.sort(keys,cmp)
-- finally, loop over the keys in sorted order, and operate
-- on elements of t
for _,k in ipairs(keys) do
f(k,t[k])
end
end
它构造一个索引,用table.sort()
对其进行排序,然后循环遍历排序索引中的每个元素,并为每个元素调用函数f
。函数f
传递键和值。排序顺序由可选的比较函数确定,该函数传递给table.sort
。调用它时需要比较两个元素(在这种情况下为表t
的键),如果第一个小于第二个,则必须返回true
。如果省略,table.sort
将使用内置的<
运算符。
例如,给出下表:
t1 = {
a = 1,
b = 2,
c = 3,
}
然后foreachinorder(t1,print)
打印:
a 1 b 2 c 3
和foreachinorder(t1,print,function(a,b) return a>b end)
打印:
c 3 b 2 a 1
答案 1 :(得分:3)
您只能对具有从1开始的连续整数键的表进行排序,即列表。如果您有另一个键值对表,您可以列出对并列出:
function sortpairs(t, lt)
local u = { }
for k, v in pairs(t) do table.insert(u, { key = k, value = v }) end
table.sort(u, lt)
return u
end
当然,只有在您提供自定义排序(lt
)时,这才有用,它需要作为参数键/值对。
在related question about sorting Lua tables中详细讨论了这个问题。
答案 2 :(得分:2)
因为他们首先没有任何订单。这就像试图整理一个装满香蕉的垃圾袋。