将随机值从数组复制到对象无法获得稳定的结果

Posted

技术标签:

【中文标题】将随机值从数组复制到对象无法获得稳定的结果【英文标题】:Can't get stable result with copying random values from array to an object 【发布时间】:2019-12-23 16:29:41 【问题描述】:

因此,我正在为锦标赛创建一个机器人,但我陷入了我想将玩家分成两组进行附加赛式锦标赛的部分。我只想随机抽取 2 个玩家,从数组中获取它们并将其作为值写入键作为对象的轮 id。另外我不应该再次使用那些球员,所以需要删除他们或smth。 代码如下:

var users = inc.funcs.getDatabase() //Getting a raw array of users (using my func that's basically a simplified fs.readFileSync func)
var tournamentPairs = new Object() //Object initialization

var id = 1
for (var i = 0; i < 16; i = i + 2) 
   var first = Math.floor(Math.random() * (users.length + 1)) //Randomizing 2 indexes
   var second = Math.floor(Math.random() * (users.length + 1))

   var player1 = client.users.get(users[first]) //Getting the players by id 
   var player2 = client.users.get(users[second])

   tournamentPairs[id++] = [player1.id, player2.id] //Writing to the object

   users.splice(first, 1) //Deleting user's indexes from the array to not use them anymore.
   users.splice(second, 1)

console.log(tournamentPairs)

它在外部运行良好,但有复制用户的坏习惯,例如,我曾经有一个 gamergod98 与 gamergod98。我试过console.log 这个废话,但在尝试console.log player2 时经常会出错,因为出于某种原因它是undefined。如果我尝试打印users[second],我会得到undefined,尽管第一个玩家从未发生过。所以我尝试了不同的方法来防止这样的情况:first == second。长话短说,它并没有太大帮助。 距离锦标赛开始还有 9 天,关于如何改进此代码的任何想法?

【问题讨论】:

您的随机数正在使用users.length + 1,因此您偶尔会得到该值或users.length,这两者都不是数组中的有效索引。你可能想看看洗牌数组而不是拉随机索引。 Getting a random value from a javascript array的可能重复 @HereticMonkey,我可能有问题的类型,但我也努力避免再次重复使用随机值。 【参考方案1】:

您收到undefined 是因为您超出了users 列表的范围。对于length 的列表,最后一个元素是list[length-1],但您生成的随机数最多为length

要修复重复的用户,请先从列表中删除第一个选定的用户,然后再选择第二个(或者为了减少破坏性的方法,标记已选定的用户)。

var id = 1
for (var i = 0; i < 16; i = i + 2) 
   var first = Math.floor(Math.random() * users.length)
   var player1 = client.users.get(users[first]) 
   users.splice(first, 1)

   var second = Math.floor(Math.random() * users.length) 
   var player2 = client.users.get(users[second])
   users.splice(second, 1)

   tournamentPairs[id++] = [player1.id, player2.id]

【讨论】:

我有一个与您的代码类似的代码,但没有得到列表长度的问题。非常感谢!【参考方案2】:

创建一个已用索引的集合,然后如果第一个或第二个在已用索引中,则继续

var usedIndices = [] ;

if (usedIndices.indexOf(first) >= 0 || 
usedIndices.indexOf(second) >= 0) 
continue;
 else  
usedIndices.push(first);
usedIndices.push(second);

将 usedIndices 变量放在 for 循环之前,将 if else 块放在第二个之后的循环内

【讨论】:

以上是关于将随机值从数组复制到对象无法获得稳定的结果的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 java 反射自动将值从 java bean 复制到 protobuf 消息对象?

Liquibase:将值从一列复制到具有数组数据类型的另一列

无法将局部变量复制到结果数组

ValueError:无法将大小为0的序列复制到维度为56的数组轴

将值从一个 DataGridView 复制到另一个

将值从ListBox复制到工作表单元格