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

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

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


当前回答

尽量避免搞乱原生原型,包括Array。原型,如果你不知道谁将使用你的代码(第三方、同事、你自己等)。

有一些方法可以安全地扩展原型(但不是在所有浏览器中),也有一些方法可以安全地使用从扩展原型创建的对象,但更好的经验法则是遵循最小意外原则,并完全避免这些做法。

如果你有时间,可以看看Andrew Dupont的JSConf 2011演讲,“Everything is allowed: Extending Built-ins”,关于这个话题的讨论。

但回到问题上来,虽然上面的解决方案是可行的,但它们过于复杂,需要不必要的计算开销。以下是我的解决方案:

function chunk (arr, len) {

  var chunks = [],
      i = 0,
      n = arr.length;

  while (i < n) {
    chunks.push(arr.slice(i, i += len));
  }

  return chunks;
}

// Optionally, you can do the following to avoid cluttering the global namespace:
Array.chunk = chunk;

其他回答

我只是在groupBy函数的帮助下写了这个。

// utils const group = (source) => ({ by: (grouping) => { const groups = source.reduce((accumulator, item) => { const name = JSON.stringify(grouping(item)); accumulator[name] = accumulator[name] || []; accumulator[name].push(item); return accumulator; }, {}); return Object.keys(groups).map(key => groups[key]); } }); const chunk = (source, size) => group(source.map((item, index) => ({ item, index }))) .by(x => Math.floor(x.index / size)) .map(x => x.map(v => v.item)); // 103 items const arr = [6,2,6,6,0,7,4,9,3,1,9,6,1,2,7,8,3,3,4,6,8,7,6,9,3,6,3,5,0,9,3,7,0,4,1,9,7,5,7,4,3,4,8,9,0,5,1,0,0,8,0,5,8,3,2,5,6,9,0,0,1,5,1,7,0,6,1,6,8,4,9,8,9,1,6,5,4,9,1,6,6,1,8,3,5,5,7,0,8,3,1,7,1,1,7,6,4,9,7,0,5,1,0]; const chunks = chunk(arr, 10); console.log(JSON.stringify(chunks));

修改自dbaseman的回答:https://stackoverflow.com/a/10456344/711085

Object.defineProperty(Array.prototype, ' chunk_efficient ', { 值:function(chunkSize) { Var数组= this; 返回[].concat.apply ([], 数组中。映射(函数(elem, i) { 返回i % chunkSize ?[]: [array.]slice(i, i + chunkSize)]; }) ); } }); console.log ( [1,2,3,4,5,6,7]. chunk_efficient (3) ) // [[1,2,3], [4,5,6], [7]]


小齿顶:

我应该指出,上面的方法(在我看来)并不是使用Array.map的一种优雅的变通方法。它基本上做以下事情,其中~是连接:

[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]

它与下面的方法具有相同的渐近运行时间,但由于构建空列表,可能是一个更糟糕的常数因子。可以重写如下(与Blazemonger的方法大致相同,这就是我最初没有提交这个答案的原因):

更有效的方法:

如果你已经定义了Array.prototype.chunk,则刷新页面 Object.defineProperty(Array.prototype, 'chunk', { 值:function(chunkSize) { var R = []; For (var I = 0;I < this.length;i += chunkSize) R.push(这一点。slice(i, i + chunkSize)); 返回R; } }); console.log ( [1, 2, 3, 4, 5, 6, 7].chunk(3) )


我现在喜欢的方式是上面的,或者是下面的一种:

Array.range = function(n) {
  // Array.range(5) --> [0,1,2,3,4]
  return Array.apply(null,Array(n)).map((x,i) => i)
};

Object.defineProperty(Array.prototype, 'chunk', {
  value: function(n) {

    // ACTUAL CODE FOR CHUNKING ARRAY:
    return Array.range(Math.ceil(this.length/n)).map((x,i) => this.slice(i*n,i*n+n));

  }
});

演示:

> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]

或者如果你不想要数组。Range函数,它实际上只是一行代码(不包括有绒毛的部分):

var ceil = Math.ceil;

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array(ceil(this.length/n)).fill().map((_,i) => this.slice(i*n,i*n+n));
}});

or

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});
in coffeescript:

b = (a.splice(0, len) while a.length)

demo 
a = [1, 2, 3, 4, 5, 6, 7]

b = (a.splice(0, 2) while a.length)
[ [ 1, 2 ],
  [ 3, 4 ],
  [ 5, 6 ],
  [ 7 ] ]

这是一个带有尾递归和数组解构的版本。

远非最快的性能,但我只是觉得好笑,js现在可以做到这一点。即使它没有为此进行优化:(

const getChunks = (arr, chunk_size, acc = []) => {
    if (arr.length === 0) { return acc }
    const [hd, tl] = [ arr.slice(0, chunk_size), arr.slice(chunk_size) ]
    return getChunks(tl, chunk_size, acc.concat([hd]))
}

// USAGE
const my_arr = [1,2,3,4,5,6,7,8,9]
const chunks = getChunks(my_arr, 2)
console.log(chunks) // [[1,2],[3,4], [5,6], [7,8], [9]]

在JS,

const splitInChunks = (arr,n) => {
  let chunksArr = [];
  if(arr !=null && arr!= undefined){
      for(i=0; i<arr.length;i+=n){
      if(arr.length-i>=n)
          chunksArr.push(arr.slice(i,i+n))
      else
           chunksArr.push(arr.slice(i,arr.length))
  }
  return chunksArr
  }
}