从数组中拼接随机名称,直到数组为空

Splicing random names from array until array is empty

我正在尝试随机选择两个名称并将它们相加。每次选择名称时,都应将其从数组中删除。函数应该 运行 直到数组为空。输出应该是在字符串或数组中配对在一起的所有名称。

var names = ['Ben', 'Mike', 'Sally', 'Joe', 'Bob', 'Sam', 'Carl', 'Frank']
//var to pick two random names from an array
function pickTwo(arr) {
  let random = Math.floor(Math.random() * arr.length);
  let random2 = Math.floor(Math.random() * arr.length);
  while (random === random2) {
    random2 = Math.floor(Math.random() * arr.length);
  }
  //remove random and random2 from array
  //run untill there are no more names in the array
  while (arr.length > 0) {
    arr.splice(random, 1);
    arr.splice(random2, 1);
    return [arr[random], arr[random2]];
  }
}
console.log(pickTwo(names));
console.log(names);

首先确保删除从数组中随机选择的 2 个名称。您拥有的函数不会执行此操作,因为从中删除名称的 arr 变量是该函数的本地变量。考虑使用在函数之前启动的全局变量 groovy,或者从函数返回 arr 变量,然后再次将其发送回函数。之后,您只需创建一个运行 pickTwo 函数的 while 循环,直到 groovy.

中没有任何内容为止
var array = [];

while(groovy.length>1){
array.push(pickTwo(groovy));
}

每次while (arr.length > 0)循环都需要得到新的随机数。否则,拼接后你的随机索引可能在数组之外,你得到 undefined.

您需要将循环中选择的每对数字推入另一个数组,return那个数组作为最终结果。

另外,当你第一次拼接时,random之后的所有索引都会向下移动。如果 random2 高于 random,您将拼接错误的元素。你应该先把高的拼接出来。

拼接后,arr[random]arr[random2] 不引用所选元素,因为您已将它们从数组中删除。 splice() return删除的元素,你应该使用那个结果。

做这件事的一个更简单的方法是随机排列数组。然后就得到每对顺序元素。

var names = ['Ben', 'Mike', 'Sally', 'Joe', 'Bob', 'Sam', 'Carl', 'Frank']
//var to pick two random names from an array
function pickTwo(arr) {
  let result = [];
  while (arr.length > 0) {
    let random = Math.floor(Math.random() * arr.length);
    let random2 = Math.floor(Math.random() * arr.length);
    while (random === random2) {
      random2 = Math.floor(Math.random() * arr.length);
    }
    //remove random and random2 from array
    //run untill there are no more names in the array
    let val1, val2;
    if (random < random2) {
      val2 = arr.splice(random2, 1)[0];
      val1 = arr.splice(random, 1)[0];
    } else {
      val1 = arr.splice(random, 1)[0];
      val2 = arr.splice(random2, 1)[0];
    }
    result.push([val1, val2]);
  }
  return result;
}
console.log(pickTwo(names));
console.log(names);

您的代码中存在一些问题:

  • randomrandom2这样random + 1 == random2random2 == arr.length - 1时,那么第二个splice就没有效果了,因为数组大小已经减小。

  • 当您在 while 循环体中 return 时,该循环将永远不会有第二次迭代。

我建议采用不同的方法:

  • 随机打乱数组
  • Return 打乱后的数组中的连续对

function shuffle(a) {
    var j, x, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = a[i];
        a[i] = a[j];
        a[j] = x;
    }
    return a;
}

function pickTwo(arr) {
    arr = shuffle([...arr]);
    return Array.from({length: arr.length >> 1}, (_, i) =>
        arr.slice(i*2, i*2+2)
    );
}

var names = ['Ben', 'Mike', 'Sally', 'Joe', 'Bob', 'Sam', 'Carl', 'Frank'];

console.log(pickTwo(names));

一种稍微修改过的方法,它使用一个单独的接受数组长度的随机化函数,主函数只是将拼接的结果从数组推入输出数组(并将结果展平,因为每个拼接都会 return 它自己的数组),然后 return 输出数组主数组为空。

const names = ['Ben', 'Mike', 'Sally', 'Joe', 'Bob', 'Sam', 'Carl', 'Frank'];

function rnd(len) {
  return Math.floor(Math.random() * len);
}

function pickTwo(arr) {

 const out = [];

  while (arr.length > 0) {
    out.push([
      arr.splice(rnd(arr.length), 1),
      arr.splice(rnd(arr.length), 1)
    ].flat());
  }

  return out;

}

console.log(pickTwo(names));

其他文档