【问题标题】:Iterate over table in order of value按值顺序迭代表
【发布时间】:2015-08-11 06:53:50
【问题描述】:

假设我有一张这样的桌子:

{
   value = 4
},
{
   value = 3
},
{
   value = 1
},
{
   value = 2
}

我想遍历它并按顺序打印值,所以输出如下:

1
2
3
4

我该怎么做,我了解如何使用 ipairspairstable.sort,但这仅在使用 table.insert 并且密钥有效时才有效,我需要在此循环值的顺序。

我尝试了一个自定义函数,但它只是以错误的顺序打印它们。

我试过了:

  • 创建索引并循环
  • 对表进行排序(抛出错误:尝试对表和表执行 __lt)
  • 还有排序、索引和其他表的组合,不仅不起作用,而且变得非常复杂。

我真的好难过。

【问题讨论】:

  • 您可以添加一些代码以便我们查看您尝试了什么吗?
  • 对不起,我在尝试后删除了它(在我的启动文件中)所以不是真的......就像我说它不起作用,只是我在黑暗中刺伤。其中大部分只是循环,循环......循环
  • 你读过lua-users.org/wiki/SortedIteration的例子吗?在那里你可以找到一个在 table 上按顺序迭代的例子(它有点复杂,但也许这就是你的意思?)。
  • table.sort(your_table, function(a,b) return a.value < b.value end)
  • @deem 我见过这个,虽然它有点太复杂了,无法理解。我可能错了,但我能找到的只是排序键的方法,而不是值。

标签: sorting lua lua-table computercraft


【解决方案1】:

对表格进行排序

这是正确的解决方案。

(抛出错误:尝试对表和表执行__lt)

听起来你尝试使用a < b

为了让 Lua 能够对值进行排序,它必须知道如何比较它们。它知道如何比较数字和字符串,但默认情况下它知道如何比较两个表。考虑一下:

local people = {
    { name = 'fred', age = 43 },
    { name = 'ted', age = 31 },
    { name = 'ned', age = 12 },
}

如果我打电话给人们sort,Lua 怎么知道我的意图?我不知道“年龄”或“姓名”是什么意思,或者我想用哪个来比较。我必须告诉它。

可以将 metatable 添加到表中,它告诉 Lua < 运算符对表的含义,但您也可以为 sort 提供一个回调函数,告诉 Lua 如何比较两个对象。

您向sort 提供一个接收两个值的函数,并使用您对表格的了解返回第一个值是否“小于”第二个值。对于您的表格:

table.sort(t, function(a,b) return a.value < b.value end)

for i,entry in ipairs(t) do
    print(i,entry.value)
end

【讨论】:

    【解决方案2】:

    如果您想保持原始表格不变,您可以创建一个自定义的“按值排序”迭代器,如下所示:

    local function valueSort(a,b)
        return a.value < b.value;
    end
    
    function sortByValue( tbl ) -- use as iterator
        -- build new table to sort
        local sorted = {};
        for i,v in ipairs( tbl ) do sorted[i] = v end;
        -- sort new table
        table.sort( sorted, valueSort );
        -- return iterator
        return ipairs( sorted );
    end
    

    当调用sortByValue() 时,它会将tbl 克隆到一个新的sorted 表中,然后对排序后的表进行排序。然后它将sorted 表交给ipairs()ipairs 输出迭代器以供for 循环使用。

    使用方法:

    for i,v in sortByValue( myTable ) do
      print(v)
    end
    

    虽然这可以确保您的原始表保持不变,但它的缺点是每次进行迭代时,迭代器都必须克隆 myTable 以创建一个新的 sorted 表,然后是 table.sort 那个 sorted 表.

    如果性能至关重要,您可以通过“缓存”sortByValue() 迭代器完成的工作来大大加快速度。更新代码:

    local resort, sorted = true;
    
    local function valueSort(a,b)
        return a.value < b.value;
    end
    
    function sortByValue( tbl ) -- use as iterator
        if not sorted then -- rebuild sorted table
            sorted = {};
            for i,v in ipairs( tbl ) do sorted[i] = v end;
            resort = true;
        end
        if resort then -- sort the 'sorted' table
            table.sort( sorted, valueSort );
            resort = false;
        end
        -- return iterator
        return ipairs( sorted );
    end
    

    每次在myTable 中添加或删除元素时,都会设置sorted = nil。这让迭代器知道它需要重建 sorted 表(并重新排序)。

    每次更新嵌套表之一中的value 属性时,设置resort = true。这让迭代器知道它必须执行table.sort

    现在,当您使用迭代器时,它会尝试并重新使用缓存 sorted 表中先前排序的结果。

    如果它找不到sorted 表(例如,在第一次使用迭代器时,或者因为你设置sorted = nil 来强制重建)它会重建它。如果它认为需要求助(例如,在第一次使用时,或者如果 sorted 表已重建,或者如果您设置了resort = true),那么它将求助于sorted 表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-25
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      相关资源
      最近更新 更多