Lua - 排序表并随机化关系

时间:2015-08-18 10:31:21

标签: sorting random lua lua-table

我有一个包含两个值的表,一个是名称(字符串和唯一),另一个是数字值(在本例中为 hearts )。我想要的是:通过 hearts 对表格进行排序,但是当存在平局时(例如 hearts 相等),可以随机搜索这些项目。通过标准排序功能,在连接的情况下,顺序总是相同的,并且每次排序功能工作时我都需要它不同。 这是一个例子:

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,这是一个随机数。然后在sort2a.hearts == b.heartsa.rnd > b.rnd订购商品。
  3. sort2中,a.hearts == b.hearts生成随机的true或false并返回它。它不起作用,我理解这是因为随机的真/假会使订单功能崩溃,因为可能存在不一致。
  4. 我不喜欢1(因为我想在排序功能中做所有事情)和2(因为它需要添加一个值),我想做3之类的工作。问题是:有没有办法以简单的方式做到这一点,这样做的最佳方式是什么? (也许,方法1或2是最佳的,我不能得到它。)

    奖金问题。此外,我需要修复一个项目并对其他项目进行排序。例如,假设我们希望"c"成为第一个。制作一个单独的表只包含要排序的项目,对表格进行排序然后添加固定项目是不是很好?

3 个答案:

答案 0 :(得分:3)

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}}

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})  -- now "c" will be the first
show(tbl)

答案 1 :(得分:2)

这是一个用于改组(加扰)数字索引表的快速函数:

ViewPager

答案 2 :(得分:1)

如果你可以自由地引入一个新的依赖项,你可以使用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)