Lua - 对表进行排序并随机化绑定

我有一个表,其中包含两个值,一个是名称(字符串且唯一),另一个是数字值(在这种情况下是心) 。我想要的是:按心排序表,但是在有一种折衷方案(例如心相等)时随机混合项目。按照标准的排序函数,在折衷方案的情况下该顺序总是相同的,而我需要每次排序函数工作时都不同。

这是一个例子:

tbl = {{name = "a", hearts = 5}, {name = "b", hearts = 2}, {name = "c", hearts = 6}, {name = "d", hearts = 2}, {name = "e", hearts = 2}, {name = "f", hearts = 7}}
sort1 = function (a, b) return a.hearts > b.hearts end
sort2 = function (a, b)
    if a.hearts ~= b.hearts then return a.hearts > b.hearts
    else return a.name > b.name end
end

table.sort(tbl, sort2)

local s = ""
for i = 1, #tbl do
    s = s .. tbl[i].name .. "(" .. tbl[i].hearts .. ") "
end
print(s)

现在,使用函数“sort2”,我认为我解决了问题。问题是,当“a.hearts == b.hearts”时会发生什么?在我的代码中,它只按其名称排序,而不是我想要的。我有两个想法:

1.首先随机混合表中的所有项目,然后应用“sort1”。 2.为表的每个元素添加一个值,称为“rnd”,该值是随机数。然后在“sort2”中,当“a.hearts == b.hearts”时,按“a.rnd> b.rnd”对项目进行排序。 3.在“sort2”中,当“a.hearts == b.hearts”时,生成随机的true或false并返回它。它不起作用,我明白这是因为随机的真/假使顺序函数崩溃,因为可能存在不一致性。

我不喜欢1(因为我想要在排序函数内做所有事情),也不喜欢2(因为它需要添加一个值),我想做类似3但有效的事情。问题是:有没有一种简单的方法来实现这一点,以及做这种事情的最佳方法是什么? (也许,方法1或2是最佳的,而我没有得到它)。

普遍问题:此外,我需要修复一个项目并对其他项目进行排序。例如,假设我们想要将“ c”放在第一位。制作只有要排序的项目的单独表,对表进行排序,然后添加固定项目是否好?

原文链接 https://stackoverflow.com/questions/32069912

点赞
stackoverflow用户1847592
stackoverflow用户1847592

-- 示例表格 local tbl = { { name = "a", hearts = 5 }, { name = "b", hearts = 2 }, { name = "c", hearts = 6 }, { name = "d", hearts = 2 }, { name = "e", hearts = 2 }, { name = "f", hearts = 7 }, }

-- 避免连续请求获得相同的结果 math.randomseed( os.time() )


-- 随机排序一个表格

-- @param tbl 要排序的表格 -- @param corrections 你的校正表格 -- function rnd_sort( tbl, corrections ) local rnd = corrections or {} table.sort( tbl, function ( a, b) rnd[a.name] = rnd[a.name] or math.random() rnd[b.name] = rnd[b.name] or math.random() return a.hearts + rnd[a.name] > b.hearts + rnd[b.name] end ) end


-- 为了调试目的,展示我们表格中的值

function show( tbl ) local s = "" for i = 1, #tbl do s = s .. tbl[i].name .. "(" .. tbl[i].hearts .. ") " end print(s) end

for i = 1, 10 do rnd_sort(tbl) show(tbl) end

rnd_sort( tbl, {c=1000000} ) -- 现在 "c" 将会是第一个 show(tbl)

2015-08-18 11:09:40
stackoverflow用户570336
stackoverflow用户570336

如果你可以引入一个新的依赖,你可以使用 lazylualinq 来为你完成这项工作(或者查看它如何对序列进行排序,如果你不需要其他功能):

local from = require("linq")

math.randomseed(os.time())

tbl = {{name = "a", hearts = 5}, {name = "b", hearts = 2}, {name = "c", hearts = 6}, {name = "d", hearts = 2}, {name = "e", hearts = 2}, {name = "f", hearts = 7}}

from(tbl)
    :orderBy("x => x.hearts")
    :thenBy("x => math.random(-1, 1)")
    :foreach(function(_, x) print(x.name, x.hearts) end)
2015-08-18 12:51:48
stackoverflow用户5240636
stackoverflow用户5240636

下面是一段快速打乱(乱序)数字索引表的函数:

function shuffle(tbl) -- 打乱数字索引
    local len, random = #tbl, math.random ;
    for i = len, 2, -1 do
        local j = random( 1, i );
        tbl[i], tbl[j] = tbl[j], tbl[i];
    end
    return tbl;
end
2015-08-23 13:32:30