无法使用关联索引对表进行排序
为什么我不能使用 table.sort 对具有关联索引的表进行排序?
Why I can't use table.sort to sort tables with associative indexes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
为什么我不能使用 table.sort 对具有关联索引的表进行排序?
Why I can't use table.sort to sort tables with associative indexes?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(3)
一般来说,Lua 表是纯关联数组。除了作为 Lua 核心中使用的特定哈希表实现的副作用之外,不存在“自然”顺序。这是有道理的,因为任何 Lua 数据类型的值(
nil
除外)都可以用作键和值;但只有字符串和数字具有任何类型的合理排序,并且仅在类似类型的值之间。例如,这张表的排序顺序应该是:
它有 1 个字符串键、1 个布尔键、1 个功能键、1 个非整数键、1 个表键和 5 个整数键。该函数应该在字符串之前排序吗?如何将字符串与数字进行比较?表格应该在哪里排序?那么恰好没有出现在该表中的
userdata
和thread
值又如何呢?按照惯例,由从 1 开始的连续整数索引的值通常用作列表。一些函数和常见的习惯用法都遵循这一约定,
table.sort
就是一个例子。对列表进行操作的函数通常会忽略存储在不属于列表的键中的任何值。同样,table.sort
是一个示例:它仅对存储在列表中的键处的元素进行排序。另一个例子是
#
运算符。对于上表,#unsortable
为 5,因为unsortable[5] ~= nil
且unsortable[6] == nil
。请注意,即使 pi 介于 3 和 4 之间,存储在数字索引math.pi
中的值也不会被计算在内,因为它不是整数。此外,其他非整数键也不会被计算在内。这意味着一个简单的 for 循环可以迭代整个列表:尽管这通常被写为
简而言之,Lua 表是无序的值集合,每个值都由一个键索引;但对于从 1 开始的连续整数键有一个特殊约定。
编辑:对于具有适当部分排序的非整数键的特殊情况,有一个涉及单独索引表的解决方法。由字符串值作为键的表的描述内容是此技巧的合适示例。
首先,以列表的形式收集新表中的键。也就是说,创建一个表,该表由从 1 开始的连续整数索引,并以键作为值,然后对其进行排序。然后,使用该索引以所需的顺序迭代原始表。
例如,这里是 foreachinorder(),它使用此技术迭代表的所有值,按照比较函数确定的顺序为每个键/值对调用一个函数。
它构建一个索引,使用
table.sort 对其进行排序()
,然后循环遍历排序索引中的每个元素,并为每个元素调用函数f
。函数f
传递键和值。排序顺序由传递给 table.sort 的可选比较函数确定。它通过两个要比较的元素(在本例中为表t
的键)来调用,并且如果第一个元素小于第二个元素,则必须返回true
。如果省略,table.sort
使用内置的<
运算符。例如,给定下表:
然后
foreachinorder(t1,print)
打印:并且
foreachinorder(t1,print,function(a,b) return a>b end)
印刷:In general, Lua tables are pure associative arrays. There is no "natural" order other than the as a side effect of the particular hash table implementation used in the Lua core. This makes sense because values of any Lua data type (other than
nil
) can be used as both keys and values; but only strings and numbers have any kind of sensible ordering, and then only between values of like type.For example, what should the sorted order of this table be:
It has one string key, one boolean key, one function key, one non-integral key, one table key, and five integer keys. Should the function sort ahead of the string? How do you compare the string to a number? Where should the table sort? And what about
userdata
andthread
values which don't happen to appear in this table?By convention, values indexed by sequential integers beginning with 1 are commonly used as lists. Several functions and common idioms follow this convention, and
table.sort
is one example. Functions that operate over lists usually ignore any values stored at keys that are not part of the list. Again,table.sort
is an example: it sorts only those elements that are stored at keys that are part of the list.Another example is the
#
operator. For the above table,#unsortable
is 5 becauseunsortable[5] ~= nil
andunsortable[6] == nil
. Notice that the value stored at the numeric indexmath.pi
is not counted even though pi is between 3 and 4 because it is not an integer. Furthermore, none of the other non-integer keys are counted either. This means that a simple for loop can iterate over the entire list:Although that is often written as
In short, Lua tables are unordered collections of values, each indexed by a key; but there is a special convention for sequential integer keys beginning at 1.
Edit: For the special case of non-integral keys with a suitable partial ordering, there is a work-around involving a separate index table. The described content of tables keyed by string values is a suitable example for this trick.
First, collect the keys in a new table, in the form of a list. That is, make a table indexed by consecutive integers beginning at 1 with keys as values and sort that. Then, use that index to iterate over the original table in the desired order.
For example, here is
foreachinorder()
, which uses this technique to iterate over all values of a table, calling a function for each key/value pair, in an order determined by a comparison function.It constructs an index, sorts it with
table.sort()
, then loops over each element in the sorted index and calls the functionf
for each one. The functionf
is passed the key and value. The sort order is determined by an optional comparison function which is passed totable.sort
. It is called with two elements to compare (the keys to the tablet
in this case) and must returntrue
if the first is less than the second. If omitted,table.sort
uses the built-in<
operator.For example, given the following table:
then
foreachinorder(t1,print)
prints:and
foreachinorder(t1,print,function(a,b) return a>b end)
prints:您只能对具有从 1 开始的连续整数键的表(即列表)进行排序。如果您有另一个键值对表,您可以创建一个键值对列表并对其进行排序:
当然,仅当您提供需要作为参数 key/ 的自定义排序 (
lt
) 时,这才有用值对。有关 Lua 表排序的相关问题中更详细地讨论了这个问题< /a>.
You can only sort tables with consecutive integer keys starting at 1, i.e., lists. If you have another table of key-value pairs, you can make a list of pairs and sort that:
Of course this is useful only if you provide a custom ordering (
lt
) which expects as arguments key/value pairs.This issue is discussed at greater length in a related question about sorting Lua tables.
因为他们一开始就没有任何订单。这就像试图对装满香蕉的垃圾袋进行分类一样。
Because they don't have any order in the first place. It's like trying to sort a garbage bag full of bananas.