【问题标题】:How to convert a list of numbers to unique pairs of two如何将数字列表转换为唯一的两个对
【发布时间】:2020-02-23 09:06:11
【问题描述】:

我有一种情况,我需要将一个由未知长度的整数组成的随机数组转换为多对 2。

例如:

var numbers = [1, 5, 0, 7, 5, 5, 1, 7, 5, 1, 2, 1];

-----------------------------------------------------
[[1, 5], [0, 7], [5, 5], [1, 7], [5, 1], [2, 1]]

需要遵守一些限制条件,例如:

  • 应该正好有 6 对(每对 2 个数字)。
  • 如果numbers 数组中的数字不足以组成 6 对,则生成一个介于 1-9 之间的数字。
  • numbers 数组中的每一项只能使用一次。
  • 每一对都必须是唯一的。但例如 [1,2][2,1] 可以被视为不同的对。
  • 一对不能包含[0, 0]

到目前为止,我发现了一个可以找到组合的函数,但是一旦它已经使用它就不会忽略索引。

var numbers = [1, 5, 0, 7, 5, 5, 1, 7, 5, 1, 2, 1];

function p(t, i) {
  if (t.length === 2) {
    result.push(t);
    return;
  }
  if (i + 1 > numbers.length) {
    return;
  }

  p(t.concat(numbers[i]), i + 1);
  p(t, i + 1);
}

var result = [];
p([], 0);
console.log(result);

接下来我该怎么做?

【问题讨论】:

  • 如何生成随机数?
  • 使用 Math.Random(),一个介于 1-9 之间的数字。

标签: javascript arrays algorithm


【解决方案1】:

您可以进行一些循环,一个用于检查结果集的长度,一个用于检查是否有可用的 array 值并添加值以获取下一对并检查该对是否以前见过。

如果没有将该对添加到结果集中并继续。

var getRandomN = n => () => Math.floor(Math.random() * n) + 1,
    getRandom = getRandomN(9),
    array = [1, 5, 0, 7],
    seen = new Set(['0|0']),
    length = 6,                        // specify wanted length
    result = [],
    i = 0,
    pair;

while (result.length < length) {       // check result with wanted length
    do {
        while (array.length < i + 2) { // check if a pair is available
            array.push(getRandom());   // if not add new random value
        }
        pair = array.slice(i, i += 2); // get a pair and increment index
    } while (seen.has(pair.join('|'))) // repeat if a pair has seen before

    seen.add(pair.join('|'));          // add a fresh pair to the set
    result.push(pair);                 // take the pair for result
}

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 谢谢你,Nina,你能在行中添加一些 cmets。我很想了解循环内部发生了什么。
  • 嗨 Nina,您的代码在结果中返回 [0, 0]-values,可以使用 seen = new Set(['0|0']), 绕过
  • 此外,它会将较长的数组(如[[1,5],[0,7],[1,6],[5,5],[5,8],[8,5],[5,1],[2,1]])裁剪为length,这可能不是所需的结果;)
  • op 只想要 6 对。
  • 但是 OP 想要前 6 对吗?
【解决方案2】:

虽然Nina 可能是正确的关于 OP 只需要来自未知长度数组的前 N ​​对,但这里有一个额外的检查(以及解决问题的稍微不同的方法):

const nums1 = [1, 5, 0, 7, 5, 5, 1, 7, 1, 5, 1, 5];
const nums2 = [1, 5, 0, 7, 5, 5, 1, 7, 5, 1, 2, 1];
const nums3 = [1, 5, 0, 7, 5, 5, 0, 0, 5, 1, 2, 1, 0, 0, 1, 8];
const nums4 = [1, 5, 0, 7, 1, 6, 5, 5, 0, 0, 5, 8, 8, 5, 5, 1, 2, 1, 0, 0, 1, 8];
const log = pairs => console.log(JSON.stringify(pairs));
log(createPairs(nums1, 6));
log(createPairs(nums2, 6));
log(createPairs(nums3, 6));
log(createPairs(nums4, 5));
log(createPairs(nums4, 5, true));

function createPairs(numbers, len, truncate) {
  let pairs = [];
  let i = 0;
  const existingValues = new Set(['0|0']);
  const randomDigit = n => Math.floor(Math.random() * (n + 1));

  // create and complete array of [len] unique pairs, not being [0, 0]
  while (pairs.length < len) {
    const pair = i + 2 <= numbers.length
      ? numbers.slice(i, i += 2) 
      : [randomDigit(9), randomDigit(9)];
    const pairStr = pair.join(`|`);
    !existingValues.has(pairStr) && pairs.push(pair);
    existingValues.add(pairStr);
  }
  
  return i + 2 < numbers.length && !truncate 
    ? `This would deliver more pairs than desired (${len})` 
    : pairs;
}
.as-console-wrapper {
  top: 0;
  max-height: 100% !important;
}

【讨论】:

  • 这段代码更接近我想要的,谢谢。
【解决方案3】:
var numbers = [1, 5, 0, 7, 5, 5, 1, 7, 5, 1, 2, 1];
var arr = [];
numbers.forEach(function (x, i) {
  if(i % 2) {
    arr[arr.length-1][1] = x;
    console.log(arr[arr.length-1]);
  }
  else {
    arr.push([x, null]);
  }
});
console.log(arr.join("#"));

【讨论】:

  • 请解释你的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多