在 Lua 中按值对表进行关联排序

发布于 2024-08-17 13:20:10 字数 899 浏览 3 评论 0原文

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

我有什么:

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

排序操作后我想要什么:

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

有什么想法吗?

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

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

不过,还是谢谢大家的帮助!

I have a key => value table I'd like to sort in Lua. The keys are all integers, but aren't consecutive (and have meaning). Lua's only sort function appears to be table.sort, which treats tables as simple arrays, discarding the original keys and their association with particular items. Instead, I'd essentially like to be able to use PHP's asort() function.

What I have:

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

What I want after the sort operation:

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

Any ideas?

Edit: Based on answers, I'm going to assume that it's simply an odd quirk of the particular embedded Lua interpreter I'm working with, but in all of my tests, pairs() always returns table items in the order in which they were added to the table. (i.e. the two above declarations would iterate differently).

Unfortunately, because that isn't normal behavior, it looks like I can't get what I need; Lua doesn't have the necessary tools built-in (of course) and the embedded environment is too limited for me to work around it.

Still, thanks for your help, all!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

凝望流年 2024-08-24 13:20:10

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

简而言之——在 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)

You seem to misunderstand something. What you have here is a associative array. Associative arrays have no explicit order on them, e.g. it's only the internal representation (usually sorted) that orders them.

In short -- in Lua, both of the arrays you posted are the same.

What you would want instead, is such a representation:

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

While you can't get them by index now (they are indexed 1, 2, 3, 4, but you can create another index array), you can sort them using table.sort.

A sorting function would be then:

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

table.sort(items, compare)
错爱 2024-08-24 13:20:10

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

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

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    

As Komel said, you're dealing with associative arrays, which have no guaranteed ordering.

If you want key ordering based on its associated value while also preserving associative array functionality, you can do something like this:

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 is {1234,3188,1004,7007}, and you can access your data like so:

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

result:

1234     bar     
3188     baz     
1004     foo     
7007     quux    
薄荷港 2024-08-24 13:20:10

嗯,错过了关于无法控制迭代的部分。 但在lua

中通常总是有办法的。

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

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

hmm, missed the part about not being able to control the iteration. there

But in lua there is usually always a way.

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

Thats a start. Now you would need to replace the pairs() that the library uses. That could be a simples as pairs=my_pairs. You could then use the solution in the link above

落花随流水 2024-08-24 13:20:10

PHP 数组与 Lua 表不同。

  • PHP 数组可能具有键值对的有序列表

  • Lua 表始终包含一组无序的键值对集合

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

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

NB Lua 允许您将连续整数键与同一表中的任何其他类型的键混合,并且表示非常高效。我有时会使用此功能,通常是用一些元数据来标记数组。

PHP arrays are different from Lua tables.

  • A PHP array may have an ordered list of key-value pairs.

  • A Lua table always contains an unordered set of key-value pairs.

A Lua table acts as an array when a programmer chooses to use integers 1, 2, 3, ... as keys. The language syntax and standard library functions, like table.sort offer special support for tables with consecutive-integer keys.

So, if you want to emulate a PHP array, you'll have to represent it using list of key-value pairs, which is really a table of tables, but it's more helpful to think of it as a list of key-value pairs. Pass a custom "less-than" function to table.sort and you'll be all set.

N.B. Lua allows you to mix consecutive-integer keys with any other kinds of keys in the same table—and the representation is efficient. I use this feature sometimes, usually to tag an array with a few pieces of metadata.

贪恋 2024-08-24 13:20:10

几个月后,我再次提出同样的问题。推荐的答案似乎指出了所需内容与 LUA 中的外观之间的差距,但它并没有让我得到我想要的东西:-这是一个按键排序的哈希。

然而,该页面上的前三个函数确实是: http://lua-users.org/wiki/SortedIteration

Coming to this a few months later, with the same query. The recommended answer seemed to pinpoint the gap between what was required and how this looks in LUA, but it didn't get me what I was after exactly :- which was a Hash sorted by Key.

The first three functions on this page DID however : http://lua-users.org/wiki/SortedIteration

同尘 2024-08-24 13:20:10

几年前我编写了一些 Lua 代码,但现在已经不太熟练了。

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

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

I did a brief bit of Lua coding a couple of years ago but I'm no longer fluent in it.

When faced with a similar problem, I copied my array to another array with keys and values reversed, then used sort on the new array.

I wasn't aware of a possibility to sort the array using the method Kornel Kisielewicz recommends.

情域 2024-08-24 13:20:10

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

这是一个增强的 compare 函数,以确保如果实际列的值相等,则它会从下一列中获取值进行评估...

{1234, "baam"} < {1234, "bar"}true 时,包含“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)

The proposed compare function works but only if the values in the first column are unique.

Here is a bit enhanced compare function to ensure, if the values of a actual column equals, it takes values from next column to evaluate...

With {1234, "baam"} < {1234, "bar"} to be true the items the array containing "baam" will be inserted before the array containing the "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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文