让我们说我有一个Javascript数组看起来如下:

["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.

什么样的方法适合将数组分成许多更小的数组,假设最多有10个元素?


当前回答

嗨,试试这个——

 function split(arr, howMany) {
        var newArr = []; start = 0; end = howMany;
        for(var i=1; i<= Math.ceil(arr.length / howMany); i++) {
            newArr.push(arr.slice(start, end));
            start = start + howMany;
            end = end + howMany
        }
        console.log(newArr)
    }
    split([1,2,3,4,55,6,7,8,8,9],3)

其他回答

好吧,让我们从一个相当严格的开始:

function chunk(arr, n) {
    return arr.slice(0,(arr.length+n-1)/n|0).
           map(function(c,i) { return arr.slice(n*i,n*i+n); });
}

它是这样使用的:

chunk([1,2,3,4,5,6,7], 2);

然后我们就有了这个紧密的减速器函数:

function chunker(p, c, i) {
    (p[i/this|0] = p[i/this|0] || []).push(c);
    return p;
}

它是这样使用的:

[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);

因为当我们将它绑定到一个数字时,小猫就死了,我们可以像这样手动curry:

// Fluent alternative API without prototype hacks.
function chunker(n) {
   return function(p, c, i) {
       (p[i/n|0] = p[i/n|0] || []).push(c);
       return p;
   };
}

它是这样使用的:

[1,2,3,4,5,6,7].reduce(chunker(3),[]);

然后是仍然非常紧凑的函数,它可以一次性完成所有操作:

function chunk(arr, n) {
    return arr.reduce(function(p, cur, i) {
        (p[i/n|0] = p[i/n|0] || []).push(cur);
        return p;
    },[]);
}

chunk([1,2,3,4,5,6,7], 3);

这里是整洁和优化的实现chunk()函数。假设默认块大小为10。

var chunk = function(list, chunkSize) {
  if (!list.length) {
    return [];
  }
  if (typeof chunkSize === undefined) {
    chunkSize = 10;
  }

  var i, j, t, chunks = [];
  for (i = 0, j = list.length; i < j; i += chunkSize) {
    t = list.slice(i, i + chunkSize);
    chunks.push(t);
  }

  return chunks;
};

//calling function
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var chunks = chunk(list);

迟到了,这是我的意见。就像很多人说的,我首先会想到的是

chunker = (a,n) => [...Array(Math.ceil(a.length/n))].map((v,i) => a.slice(i*n, (i+1)*n))

但我更喜欢但还没看到的是:

chunker = (n) => (r,v,i) => (c = Math.floor(i/n), (r[c] = r[c] || []).push(v), r)

console.log(arr.reduce(chunker(3), []))

有更长的变体

chunker = (a, n) => a.reduce((r,v,i) => {
  c = Math.floor(i/n); // which chunk it belongs to
  (r[c] = r[c] || []).push(v)
  return r
}, [])

console.log(chunker(arr, 3))

解释

常见的答案将首先确定块的数量,然后根据块所在的位置和每个块的大小获得原始数组的切片 块减速器函数将遍历每个元素,并将其放入相应评估的块数组中。

性能几乎相同,据我所见,reduce方法平均慢了4%。

PS: reduce(ing)的优点是很容易改变分组标准。在问题和例子中,标准是相邻的单元格(映射使用切片)。但是你可能想要在“循环”中做它,例如,使用mod (% operator),或任何其他数学公式

重新阅读它让我发现这个公式也可以是一个参数,导致一个更通用的解决方案,需要2个函数来实现答案:

splitter = (a, f) => a.reduce((r,v,i) => { // math formula and/or function
  c = f(v, i) || 0; // custom formula, receiving each value and index
  (r[c] = r[c] || []).push(v)
  return r
}, [])

chunker = (a, n) => splitter(a, (v,i) => Math.floor(i/n))

console.log(chunker(arr, 3))
console.log(splitter(arr, (v,i) => v % 2))  // is it even or odd?

splitter也可以用于创建命名数组,也就是对象,函数返回字符串而不是数字:)

下面是我使用Coffeescript列表理解的方法。可以在这里找到一篇详细介绍Coffeescript中的理解的好文章。

chunk: (arr, size) ->
    chunks = (arr.slice(index, index+size) for item, index in arr by size)
    return chunks

我更喜欢使用splice方法:

var chunks = function(array, size) {
  var results = [];
  while (array.length) {
    results.push(array.splice(0, size));
  }
  return results;
};