如何使用Javascript从特定的单个数组中查找所有不重复的组合

Posted

技术标签:

【中文标题】如何使用Javascript从特定的单个数组中查找所有不重复的组合【英文标题】:How to find all no repeat combinations form specific single arrays use Javascript 【发布时间】:2021-11-13 20:21:55 【问题描述】:

我是一名 javascript 初学者,我有一个个人项目来使用程序来查找特定数组中所有可能且不重复的组合

我假设有 3 套产品,每套有 10 种款式,比如这个数组

[1,2,3,4..10,1,2,4...8,9,10]

①②③④⑤⑥⑦⑧⑨⑩
①②③④⑤⑥⑦⑧⑨⑩
①②③④⑤⑥⑦⑧⑨⑩

总数组长度 = 30

我打算将它随机分成5个孩子,但他们不能重复相同的产品风格

确定结果: ①②③④⑤⑥ ✔ ②③④⑤⑥⑦ ✔ ①②③⑧⑨⑩ ✔ ④⑥⑦⑧⑨⑩ ✔ ①⑤⑦⑧⑨⑩ ✔

每个人都可以平均分配不重复的产品

错误: ①②③④⑤⑥ ✔ ①②③④⑤⑦ ✔ ①②⑥⑧⑨⑩ ✔ ③④⑤⑦⑧⑨ ✔ ⑥⑦⑧⑨⑩⑩✘(因为10号重复)


我的解决方案是随机分配5组数组,然后使用“new Set(myArray[i]).size;”检查值 sum 是否为 30,使用 [do..white],而 sum 不是 30 然后重复执行随机分配功能,直到结果不重复。

像这样:

function splitArray() 
  
    do 
      var productArray = [1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10];  //Just for sample, actualy this array will be more then 30
      var productPerChildArray = [];
      for (var i = 0; i < 5; i++) 
        GroupNum = [];
  
        for (var v = 0; v < 6; v++) 
          var selectNum = productArray[Math.floor(Math.random() * productArray.length)];
          GroupNum.push(selectNum);
          productArray = removeItemOnce(productArray, selectNum);
        
  
        productPerChildArray.push(GroupNum);
      
     while (checkIfArrayIsUnique(productPerChildArray));
  
    return productPerChildArray;
  
  
  //---------check repeat or not----------
  function checkIfArrayIsUnique(myArray) 
    var countRight  = 0;
    for (var i = 0; i < myArray.length; i++) 
      countRight += new Set(myArray[i]).size;
    
    return (countRight != 5*6);
  

  //----------update productArray status----------
function removeItemOnce(arr, value) 
    var index = arr.indexOf(value);
    if (index > -1) 
      arr.splice(index, 1);
    
    return arr;
  

  console.log(splitArray());

似乎可以解决问题,但实际上 productArray 不是必须 30,此解决方案将花费大量时间尝试不重复组合。效率低

我相信他们有比我的想法更好的解决问题的其他解决方案

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

我的方法是:只需将下一个数字放在随机选择的 array 中 - 当然,过滤掉那些已经包含下一个数字的数字。

// the beginning dataset
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

// the size of the groups to be formed (must divide the
// size of beginning dataset without a remainder)
const ARR_LENGTH = 6

// creating the array that will be filled randomly
const getBaseArray = ( data, arrLength ) => 
  const num = parseInt(data.length / arrLength, 10)
  return Array.from(Array(num), () => [])


// filter arrays that satisfy conditions
const conditions = ( subArr, val ) => 
  if (subArr.includes(val)) return false
  if (ARR_LENGTH <= subArr.length) return false
  return true

const getArraysFiltered = ( val, arr ) => 
  return arr
    .map((e, i) => (
      origIdx: i,
      subArr: e,
    ))
    .filter(( subArr ) => conditions( subArr, val ))


// select a random array from a list of arrays
const getRandomArrIdx = ( arr ) => 
  return Math.floor(Math.random() * arr.length)


// get the original array index from the filtered values
const getArrIdx = ( val, arr ) => 
  const filtered = getArraysFiltered( val, arr )
  if (!filtered.length) return -1

  const randomArrIdx = getRandomArrIdx( arr: filtered )
  return filtered[randomArrIdx].origIdx


const getFinalArr = ( data ) => 
  // short circuit: if the data cannot be placed in
  // arrays evenly, then it's a mistake (based on
  // the current ruleset)
  if (data.length % ARR_LENGTH) return [false]

  // creating the array that will hold the numbers
  const arr = getBaseArray( data, arrLength: ARR_LENGTH )
 
  let i = 0;
  for (i; i < data.length; i++) 
    const idx = getArrIdx(
      val: data[i],
      arr,
    )
    // if there's no place that the next number could be
    // placed, then break (prematurely), so the algorithm
    // can be restarted as early as possible
    if (idx === -1) break;
    arr[idx].push(data[i])
  

  if (i < data.length) 
    // restart algorithm if we couldn't place
    // all the numbers in the dataset
    return getFinalArr( data )
   else 
    return arr
  



// constructing the final array of arrays & logging them:
console.log('res', getFinalArr( data ).join(' '))
console.log('res', getFinalArr( data ).join(' '))
console.log('res', getFinalArr( data ).join(' '))
console.log('res', getFinalArr( data ).join(' '))

我不知道它是否更有效,但我发现这个问题很有趣。

现在,算法是

分解成小的逻辑步骤 易于理解 根据需要轻松调整 适用于所有大小的数据(如果要创建的组可以平均填充)

【讨论】:

非常感谢,太完美了~我还在学习Javascript。所以我会试着理解这个理论。

以上是关于如何使用Javascript从特定的单个数组中查找所有不重复的组合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript/jQuery 中查找数组是不是包含特定字符串?

如何从javascript中的数组中删除单个实例? [复制]

JavaScript如何从数组中删除特定数据

如何在javascript中从多个数组中获取单个数组[重复]

如何从熊猫框架中的特定列中提取numpy数组并将它们堆叠为单个numpy数组[重复]

如何使用单个命令在当前工作目录的父目录和子目录中查找具有特定模式的文件?