【问题标题】:Split Array of items into N Arrays将项目数组拆分为 N 个数组
【发布时间】:2017-03-03 03:33:43
【问题描述】:

我想将一个数字数组拆分为 N 个组,这些组必须从 largersmaller 组排序。

例如,在下面的代码中,将一个 12 个数字的 Array 拆分为 5 个 Array,结果应该从大(组)到小,平均拆分:

source: [1,2,3,4,5,6,7,8,9,10,11,12]
  ⬇      
output: [1,2,3] [4,5,6] [7,8] [9,10] [11,12]

Playground

// set up known variables
var arr = [1,2,3,4,5,6,7,8,9,10,11,12],
    numberOfGroups = 5,
    groups = [];

// split array into groups of arrays
for(i=0; i<arr.length; i++) {
  var groupIdx = Math.floor( i/(arr.length/numberOfGroups) );
  
  // if group array isn't defined, create it
  if( !groups[groupIdx] ) 
    groups[groupIdx] = [];
  // add arr value to group
  groups[groupIdx].push( arr[i] )
  
}

// Print result
console.log( "data: ", arr );
console.log( "groups: ", groups )

更新:

感谢 SimpleJ 的 answer,我可以完成我的工作。
用例是一种将 HTML 列表拆分为“分块”列表的算法,这是使用 CSS Columns 无法轻松实现的想法。

Demo page

【问题讨论】:

  • 我不明白基于什么数组应该被拆分?为什么前 2 个数组包含 3 个数字而另一个仅包含 2 个?无论如何,如果您想按长度对拆分的数组进行排序,您可以使用 sort:groups = groups.sort(function(g1, g2) { return g1.length &lt; g2.length; })
  • "我在谷歌上搜索并看到了一些其他答案,但没有什么是我想要的......" - 那么你到底想要什么?您如何确定组大小,逻辑是什么?现有答案如何无法满足您的要求?您自己的代码如何无法满足您的要求?
  • @GershonPapi - 他们根据逻辑进行拆分,以使它们尽可能均匀,但永远不要在一个较小的群体之后再拥有一个更大的群体。

标签: javascript arrays math


【解决方案1】:

我不是 100% 确定这应该如何在具有不同组数的不同大小的数组上工作,但这适用于您的 12 位示例:

function chunkArray(arr, chunkCount) {
  const chunks = [];
  while(arr.length) {
    const chunkSize = Math.ceil(arr.length / chunkCount--);
    const chunk = arr.slice(0, chunkSize);
    chunks.push(chunk);
    arr = arr.slice(chunkSize);
  }
  return chunks;
}



var arr = [1,2,3,4,5,6,7,8,9,10,11,12];
console.log( chunkArray(arr, 5) )

【讨论】:

  • 顺便说一句,你为什么用const而不是var,哪个更短?
  • 我只是更喜欢const 在变量不会改变的任何情况下。如果您担心文件大小,varlet 可以正常工作。如果你使用 Babel,const 将编译成 var
  • 我明白了。我当然使用 Babel :) 非常感谢您非常花时间回答我的问题!
【解决方案2】:

我认为这更像是一个数学问题而不是 Javascript。

const getGroups = (arr, noOfGroups) => {
  const division = Math.floor(arr.length / numberOfGroups);
  const groups = [[]];
  let remainder = arr.length % numberOfGroups;
  let arrIndex = 0;
  for (let i = 0; i < noOfGroups; i++) {
    for (let j = division + (!!remainder * 1); j >= 0; j--) {
      groups[i].push(arr[arrIndex]);
      arrIndex += 1;
    }
    remainder -= 1;
  }

  return groups;
};

const myGroups = getGroups([1,2,3,4,5,6,7,8,9,10,11,12], 5);

myGroups 将是 [[1, 2, 3], [4, 5, 6], [7, 8], [9, 10], [11, 12]]

这适用于任意数量的团体和玩家

【讨论】:

  • 谢谢,但这比接受的答案更好吗?
  • @vsync - 感谢您查看我的回答。如果我们比较复杂性,我可以说这是一个更好的解决方案。我的答案的复杂性 = 组数 * 组中元素的平均数,在给定情况下为 5 * 2.4 = 12。 2.4 是因为 3 出现两次,2 出现三次。接受答案的复杂性 = 组数 * 2 * 剩余 arr 的长度。这里 slice 使用了两次,我认为这是一个繁重的操作,因为它在内部迭代整个数组。
【解决方案3】:

@SimpleJ 答案的较短版本,没有使用两次切片。

function splitArrayEvenly(array, n) {
  array = array.slice();
  let result = [];
  while (array.length) {
    result.push(array.splice(0, Math.ceil(array.length / n--)));
  }
  return result;
}

console.log(splitArrayEvenly([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 5))

【讨论】:

    猜你喜欢
    • 2012-01-01
    • 2013-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-09-29
    • 2021-09-19
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多