首页 > 解决方案 > 如何在javascript中有效地从Array中选择两个随机索引而不会重复?

问题描述

我有一个数组数组,我需要选择 (index1, index2) 的 2 个随机和不同的组合

让我举个例子

data = [["a", "b", "c", "d"], ["e", "g"], ["i", "j", "k"]]

我需要有 (index1: 0 , index2: 2) 和 (index1: 2 , index2: 1)

我怎样才能有效地做到这一点?

标签: javascript

解决方案


首先,您可以创建一个组合:

const i11 = Math.floor(Math.random() * data.length);
const i12 = Math.floor(Math.random() * data[i11].length);

然后您可以检查内部数组是否只有一个元素。如果它只有一个元素并且是第一个组合,则应在以下步骤中忽略它:

const dataLength = data[i11].length > 1 ? data.length : data.length - 1;

现在您可以为第二个组合生成外部索引并对其进行调整:

let i21 = Math.floor(Math.random() * dataLength);
if (i21 >= i11 && data[i11].length === 1) ++i21;

接下来可以检查第一个组合的外部索引和第二个组合的外部索引是否相同,并进行相同的调整以避免重复:

const innerDataLength = i21 === i11 ? data[i21].length - 1 : data[i21].length;

最后你可以生成第二个内部索引并调整它

let i22 = Math.floor(Math.random() * innerDataLength);
if (i21 === i11 && i22 >= i12) ++i22;

整个代码作为一个带有测试的函数:

const data = [["a", "b", "c", "d"], ["e", "g"], ["i", "j", "k"]];

function combinations(data) {
  const i11 = Math.floor(Math.random() * data.length);
  const i12 = Math.floor(Math.random() * data[i11].length);

  const dataLength = data[i11].length > 1 ? data.length : data.length - 1;

  let i21 = Math.floor(Math.random() * dataLength);
  if (i21 >= i11 && data[i11].length === 1) ++i21;

  const innerDataLength = i21 === i11 ? data[i21].length - 1 : data[i21].length;
  let i22 = Math.floor(Math.random() * innerDataLength);
  if (i21 === i11 && i22 >= i12) ++i22;
  
  return [[i11, i12], [i21, i22]];
}

console.log(combinations(data));

for (let i = 0; i < 10000; ++i) {
    const [[i11, i12], [i21, i22]] = combinations(data);
    if (i11 === i21 && i12 == i22) console.log('Test failed!');
}


推荐阅读