如何按字母顺序对简单的 Lua table 进行排序?

How do I sort a simple Lua table alphabetically?

我已经看过很多线程的例子,说明如何做到这一点,问题是,我还是做不到。

所有的例子都有 tables 额外的数据。例如像这样的

lines = {
  luaH_set = 10,
  luaH_get = 24,
  luaH_present = 48,
}

或者这个,

obj = {
   { N = 'Green1'      },
   { N = 'Green'       },
   { N = 'Sky blue99'  }
}

我可以用几种语言编写代码,但我对 Lua 还很陌生,而且 table 真的让我感到困惑。我似乎无法弄清楚如何调整示例中的代码以便能够对简单的 table.

进行排序

这是我的 table:

local players = {"barry", "susan", "john", "wendy", "kevin"}

我想按字母顺序对这些名称进行排序。我知道 Lua tables 不保持顺序,这让我感到困惑。我真正关心的只是按字母顺序打印这些名称,但我觉得我需要正确地学习它并知道如何以正确的顺序将它们索引到新的 table.

我看到的例子是这样的:

local function cmp(a, b)
   a = tostring(a.N)
   b = tostring(b.N)
   local patt = '^(.-)%s*(%d+)$'
   local _,_, col1, num1 = a:find(patt)
   local _,_, col2, num2 = b:find(patt)
   if (col1 and col2) and col1 == col2 then
      return tonumber(num1) < tonumber(num2)
   end
   return a < b
end

table.sort(obj, cmp)
for i,v in ipairs(obj) do
   print(i, v.N)
end

或者这个:

function pairsByKeys (t, f)
  local a = {}
  for n in pairs(t) do table.insert(a, n) end
  table.sort(a, f)
  local i = 0      -- iterator variable
  local iter = function ()   -- iterator function
    i = i + 1
    if a[i] == nil then return nil
    else return a[i], t[a[i]]
    end
  end
  return iter
end

for name, line in pairsByKeys(lines) do
  print(name, line)
end

关于如何为简单的 1D 执行相同的操作,我完全被这个问题所困扰 table。

任何人都可以帮助我理解这一点吗?我知道如果我能理解最基本的例子,我就能自学这些更难的例子。

local players = {"barry", "susan", "john", "wendy", "kevin"}

-- sort ascending, which is the default
table.sort(players)
print(table.concat(players, ", "))

-- sort descending
table.sort(players, function(a,b) return a > b end)
print(table.concat(players, ", "))

原因如下:

你的tableplayers是一个序列。

local players = {"barry", "susan", "john", "wendy", "kevin"}

相当于

local players = {
  [1] = "barry",
  [2] = "susan",
  [3] = "john",
  [4] = "wendy",
  [5] = "kevin",
}

如果您不在 table 构造函数中提供键,Lua 将自动使用整数键。

像这样的table可以按其值排序。 Lua 将根据比较函数的 return 值简单地重新排列索引值对。默认情况下,这是

function (a,b) return a < b end

如果你想要任何其他顺序,你需要提供一个函数,如果元素 ab

之前返回 true

读这个https://www.lua.org/manual/5.4/manual.html#pdf-table.sort

table.sort Sorts the list elements in a given order, in-place, from list[1] to list[#list]

此示例不是“列表”或序列:

lines = {
  luaH_set = 10,
  luaH_get = 24,
  luaH_present = 48,
}

相当于

lines = {
  ["luaH_set"] = 10,
  ["luaH_get"] = 24,
  ["luaH_present"] = 48,
}

它只有字符串作为键。它没有顺序。您需要一个辅助序列来将一些顺序映射到 table 的元素。

第二个例子

obj = {
   { N = 'Green1'      },
   { N = 'Green'       },
   { N = 'Sky blue99'  }
}

相当于

obj = {
  [1] = { N = 'Green1'      },
  [2] = { N = 'Green'       },
  [3] = { N = 'Sky blue99'  },
}

是一个列表。所以你可以对它进行排序。但是按 table 值排序并没有多大意义。所以你需要提供一个功能,让你有一个合理的方式来订购它。

阅读本文,您将了解在这方面什么是“序列”或“列表”。这些名称也用于其他事物。不要让它迷惑你。

https://www.lua.org/manual/5.4/manual.html#3.4.7

它基本上是一个 table,具有从 1 开始的连续整数键。

了解这种差异是学习时最重要的概念之一 Lua。 table 库的长度运算符、ipairs 和许多函数仅适用于序列。

澄清关于“不保留顺序”的混淆:不保留顺序的是 table 中值的 keys,特别是对于字符串键,即当您将 table 用作字典而不是数组时。如果你写 myTable = {orange="hello", apple="world"} 那么你在键 apple 左边定义键 orange 的事实不会被存储。如果你使用 for k, v in pairs(myTable) do print(k, v) end 枚举 keys/values 那么你实际上会在 orange hello 之前得到 apple world 因为 "apple" < "orange".

虽然你没有数字键的这个问题(如果你不指定它们,默认情况下键是什么 - myTable = {"hello", "world", foo="bar"}myTable = {[1]="hello", [2]="world", foo="bar"} 相同,即它将分配 myTable[1] = "hello"myTable[2] = "world"myTable.foo = "bar"(与 myTable["foo"] 相同)。(在这里,即使您 得到数字键的顺序是随机的——你不需要,这没关系,因为你仍然可以通过递增来循环它们。)

您可以使用 table.sort,如果没有给出排序函数,将使用 < 对值进行排序,因此对于数字,结果是升序数字,对于字符串,它将排序通过 ASCII 码:

local players = {"barry", "susan", "john", "wendy", "kevin"}
table.sort(players)
-- players is now {"barry", "john", "kevin", "susan", "wendy"}

然而,如果您混合了小写和大写条目,这将分崩离析,因为由于 ASCII 代码较低,大写字母将排在小写字母之前,当然它也无法与 non-ASCII 字符(如元音变音)一起正常工作(他们会排在最后)- 这不是字典排序。

然而,您可以提供自己的排序函数,它接收参数 (a, b) 并且需要 return true 如果 a 应该在 b 之前。这是一个修复 lower-/uppercase 问题的示例,例如,通过在比较之前转换为大写:

table.sort(players, function (a, b)
  return string.upper(a) < string.upper(b)
end)

This is my table:
local players = {"barry", "susan", "john", "wendy", "kevin"}
I want to sort these names alphabetically.

你只需要 table.sort(players)

I understand that LUA tables don't preserve order.

不保留 Lua table(具有任意键的字典)中的字段顺序。
但是你的 Lua table 是一个数组,它是 self-ordered 通过它的整数键 1, 2, 3,....