[英]Lua - Sort table and randomize ties
I have a table with two values, one is a name (string and unique) and the other is a number value (in this case hearts ).我有一个包含两个值的表,一个是名称(字符串和唯一值),另一个是数值(在本例中为heart )。 What I want is this: sort the table by hearts but scramble randomly the items when there is a tie (eg hearts is equal).
我想要的是:按红心对桌子进行排序,但在平局时随机打乱项目(例如红心相等)。 By a standard sorting function, in case of ties the order is always the same and I need it to be different every time the sorting function works.
通过标准的排序功能,在平局的情况下,顺序总是相同的,每次排序功能工作时我都需要它不同。 This is anexample:
这是一个例子:
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)
Now, with the function sort2
I think I quite got the problem.现在,使用
sort2
函数,我想我完全有问题。 The problem is, what happens when a.hearts == b.hearts
?问题是,当
a.hearts == b.hearts
时会发生什么? In my code it just orders the ties by their name, not what I want.在我的代码中,它只是按名称排序关系,而不是我想要的。 I have two ideas:
我有两个想法:
sort1
.sort1
。rnd
, that is a random number.rnd
,这是一个随机数。 Then in sort2
, when a.hearts == b.hearts
order the items by a.rnd > b.rnd
.sort2
,当a.hearts == b.hearts
按a.rnd > b.rnd
对项目进行a.rnd > b.rnd
。sort2
, when a.hearts == b.hearts
generate randomly true or false and return it.sort2
,当a.hearts == b.hearts
随机生成 true 或 false 并返回它。 It doesn't work, and I understand that this happens because the random true/false makes the order function crash since there could be inconsistencies. I don't like 1 (because I would like to do everything inside the sorting function) and 2 (since it requires to add a value), I would like to do something like 3 but working.我不喜欢 1(因为我想在排序函数中做所有事情)和 2(因为它需要添加一个值),我想做类似 3 的事情但可以工作。 The question is: is there a way do to this in a simple manner, and what is an optimal way of doing this?
问题是:有没有办法以简单的方式做到这一点,这样做的最佳方法是什么? (maybe, method 1 or 2 are optimal and I don't get it).
(也许,方法 1 或 2 是最佳的,我不明白)。
Bonus question.奖金问题。 Moreover, I need to fix an item and sort the others.
此外,我需要修复一个项目并对其他项目进行排序。 For example, suppose we want
"c"
to be first.例如,假设我们希望
"c"
在第一位。 Is it good to make a separate table with only the items to sort, sort the table and then add the fixed items?制作一个单独的表格,只有要排序的项目,对表格进行排序然后添加固定项目是否好?
-- example table
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 },
}
-- avoid same results on subsequent requests
math.randomseed( os.time() )
---
-- Randomly sort a table
--
-- @param tbl Table to be sorted
-- @param corrections Table with your 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
---
-- Show the values of our table for debug purposes
--
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)
Here's a quick function for shuffling (scrambling) numerically indexed tables:这是一个用于打乱(打乱)数字索引表的快速函数:
function shuffle(tbl) -- suffles numeric indices
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
If you are free to introduce a new dependency, you can use lazylualinq to do the job for you (or check out how it sorts sequences, if you do not need the rest):如果您可以随意引入新的依赖项,则可以使用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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.