【问题标题】:Associatively sorting a table by value in Lua在 Lua 中按值关联地对表进行排序
【发布时间】:2022-05-13 18:15:18
【问题描述】:

我有一个键 => 值表,我想在 Lua 中排序。键都是整数,但不是连续的(并且有意义)。 Lua 唯一的排序函数似乎是table.sort,它将表视为简单数组,丢弃原始键及其与特定项目的关联。相反,我基本上希望能够使用PHP's asort() 函数。

我有什么:

items = {
    [1004] = "foo",
    [1234] = "bar",
    [3188] = "baz",
    [7007] = "quux",
}

排序操作后我想要什么:

items = {
    [1234] = "bar",
    [3188] = "baz",
    [1004] = "foo",
    [7007] = "quux",
}

有什么想法吗?

编辑:根据答案,我假设这只是我正在使用的特定嵌入式 Lua 解释器的一个奇怪的怪癖,但在我的所有测试中,pairs()始终按照添加到表中的顺序返回表项。 (即上述两个声明的迭代方式不同)。

不幸的是,因为这不是正常行为,我似乎无法得到我需要的东西; Lua 没有内置(当然)必要的工具,而且嵌入式环境太有限,我无法解决它。

不过,谢谢大家的帮助!

【问题讨论】:

  • 这两张表一模一样。

标签: sorting lua lua-table asort


【解决方案1】:

你好像误会了什么。您在这里拥有的是associative array。关联数组没有明确的顺序,例如它只是对它们进行排序的内部表示(通常是排序的)。

简而言之——在 Lua 中,您发布的两个数组都相同

您想要的是这样的表示:

items = {
    {1004, "foo"},
    {1234, "bar"},
    {3188, "baz"},
    {7007, "quux"},
}

虽然您现在无法通过索引获取它们(它们的索引为 1、2、3、4,但您可以创建另一个索引数组),但您可以使用 table.sort 对它们进行排序。

排序函数将是:

function compare(a,b)
  return a[1] < b[1]
end

table.sort(items, compare)

【讨论】:

  • 根据我的测试,这对于 Lua 来说似乎不是真的。使用pairs() 迭代表时,顺序是稳定的,并且与添加项目的顺序相对应。此外,我没有选择更改数据存储方式的选项;我将结果输入到第 3 方库中,该库以“pairs() order”向用户显示项目。
  • pairs 以哈希顺序返回数据 - 它可能是稳定的 - 但它不是添加项目的顺序。来自 lua-users wiki “注意,当使用字典时,不能保证键存储在表中的顺序,因此不能保证使用 pair() 检索键的顺序。这个警告​​甚至适用于索引表的一部分,或者在根本不用作字典并且只有索引作为键的表中。”
  • 顺便说一句,return a[0] &lt; b[0] 也咬我太多次了。 Lua 索引是从 1 开始的。
  • @Stavros - 天哪,这太奇怪了,以至于有人花了这么长时间才注意到它!
  • 既然要比较字符串,不应该是return a[2] &lt; b[2]吗?
【解决方案2】:

正如 Komel 所说,您正在处理关联数组,它们没有保证顺序。

如果您希望基于关联值的键排序同时保留关联数组功能,您可以执行以下操作:

function getKeysSortedByValue(tbl, sortFunction)
  local keys = {}
  for key in pairs(tbl) do
    table.insert(keys, key)
  end

  table.sort(keys, function(a, b)
    return sortFunction(tbl[a], tbl[b])
  end)

  return keys
end

items = {
    [1004] = "foo",
    [1234] = "bar",
    [3188] = "baz",
    [7007] = "quux",
}

local sortedKeys = getKeysSortedByValue(items, function(a, b) return a < b end)

sortedKeys 是 {1234,3188,1004,7007},您可以像这样访问您的数据:

for _, key in ipairs(sortedKeys) do
  print(key, items[key])
end

结果:

1234     bar     
3188     baz     
1004     foo     
7007     quux    

【讨论】:

  • 你刚刚拯救了我的一天,几个小时以来一直在为桌子排序而苦苦挣扎。血腥的命令..
【解决方案3】:

嗯,错过了无法控制迭代的部分。那里

但在 lua 中通常总有办法。

http://lua-users.org/wiki/OrderedAssociativeTable

这是一个开始。现在您需要替换库使用的pairs()。这可能是pairs = my_pairs的简单。然后您可以使用上面链接中的解决方案

【讨论】:

    【解决方案4】:

    PHP 数组不同于 Lua 表。

    • PHP 数组可能有一个 有序列表 键值对。

    • Lua 表总是包含一个无序集的键值对。

    当程序员选择使用整数 1, 2, 3, ... 作为键时,Lua 表充当数组。语言语法和标准库函数,如 table.sort 为具有连续整数键的表提供特殊支持。

    所以,如果你想模拟一个 PHP 数组,你必须使用键值对列表来表示它,这实际上是一个表的表,但将其视为键列表会更有帮助-值对。将自定义的“小于”函数传递给table.sort,一切就绪。

    注意Lua 允许您在 same 表中将连续整数键与任何其他类型的键混合 — 并且表示是有效的。我有时会使用这个功能,通常是用一些元数据标记一个数组。

    【讨论】:

      【解决方案5】:

      几个月后,使用相同的查询。推荐的答案似乎指出了所需的内容与在 LUA 中的外观之间的差距,但它并没有让我得到我真正想要的东西:- 这是一个按 Key 排序的哈希。

      然而,此页面上的前三个函数 DID:http://lua-users.org/wiki/SortedIteration

      【讨论】:

      • 但这恰恰是相反的问题:这个问题是按值排序。您的答案是按键排序
      【解决方案6】:

      几年前我做了一点 Lua 编码,但我不再流利了。

      当遇到类似问题时,我将我的数组复制到另一个数组,键和值颠倒,然后在新数组上使用sort

      我不知道可以使用 Kornel Kisielewicz 推荐的方法对数组进行排序。

      【讨论】:

        【解决方案7】:

        建议的 compare 函数有效,但前提是第一列中的值是唯一的。

        这里有一点增强的compare 函数,以确保如果实际列的值相等,它会从下一列中获取值来评估...

        如果{1234, "baam"} &lt; {1234, "bar"}true items,则包含“baam”的数组将插入到包含“bar”的数组之前。

        local items = {
            {1004, "foo"},
            {1234, "bar"},
            {1234, "baam"},
            {3188, "baz"},
            {7007, "quux"},
        }
        
        local function compare(a, b)
            for inx = 1, #a do
                -- print("A " .. inx .. " " .. a[inx])
                -- print("B " .. inx .. " " .. b[inx])
        
                if a[inx] == b[inx] and a[inx + 1] < b[inx + 1] then
                    return true
                elseif a[inx] ~= b[inx] and a[inx] < b[inx] == true then
                    return true
                else
                    return false
                end
            end
            return false
        end
        
        table.sort(items,compare)
        

        【讨论】:

          猜你喜欢
          • 2011-01-03
          • 2023-03-23
          • 2020-02-08
          • 2014-03-20
          • 2011-10-07
          • 1970-01-01
          • 2013-03-20
          • 2020-10-17
          • 1970-01-01
          相关资源
          最近更新 更多