ChatGPT解决这个技术问题 Extra ChatGPT

将数组拆分为块

假设我有一个 Javascript 数组,如下所示:

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

什么方法适合将数组分块(拆分)成许多较小的数组,比如说最多 10 个元素?

对于 lodash 个用户,您正在寻找 _.chunk
如果您还需要最后一个块的最小大小,请使用以下选项:stackoverflow.com/questions/57908133/…
我创建了一个合并了最佳答案的解决方案:stackoverflow.com/a/71483760/2290538

3
3limin4t0r

array.slice() 方法可以根据您的需要从数组的开头、中间或结尾提取切片,而无需更改原始数组。

const chunkSize = 10;
for (let i = 0; i < array.length; i += chunkSize) {
    const chunk = array.slice(i, i + chunkSize);
    // do whatever
}

最后一个 chunk 可能小于 chunkSize。例如,当给定 12 个元素的 array 时,第一个块将有 10 个元素,第二个块只有 2 个。

请注意,0chunkSize 将导致无限循环。


请记住,如果这是一个断言 chunk0 的 util 函数。 (无限循环)
不,最后一块应该比其他块小。
@Blazemonger,确实!下次我会在下结论之前亲自尝试一下。我假设(错误地)将超出数组边界的输入传递给 array.slice 将是一个问题,但它工作得非常完美!
对于单行者(链爱好者)const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size));
为什么需要j?首先我认为这是一个优化,但它实际上比 for(i=0;i
R
Raphael Pinel

这是一个使用 reduce 的 ES6 版本

const perChunk = 2 // 每个块的项目 const inputArray = ['a','b','c','d','e'] const result = inputArray.reduce((resultArray, item, index) => { const chunkIndex = Math.floor(index/perChunk) if(!resultArray[chunkIndex]) { resultArray[chunkIndex] = [] // 开始一个新块 } resultArray[chunkIndex].push(item) return resultArray }, [])控制台.log(结果); // 结果:[['a','b'], ['c','d'], ['e']]

并且您已准备好链接进一步的 map/reduce 转换。您的输入数组保持不变

如果您更喜欢较短但可读性较差的版本,您可以在混合中加入一些 concat 以获得相同的最终结果:

inputArray.reduce((all,one,i) => {
   const ch = Math.floor(i/perChunk); 
   all[ch] = [].concat((all[ch]||[]),one); 
   return all
}, [])

您可以使用余数运算符将连续项目放入不同的块中:

const ch = (i % perChunk); 

这似乎是最简洁的解决方案。 chunkIndex = Math.floor(index/perChunk) 得到什么?是平均值吗?
5/2 = 2.5Math.floor(2.5) = 2,因此索引为 5 的项目将放置在存储桶 2 中
我喜欢您在此处使用 allone - 与我见过的其他示例相比,reduce 更容易读懂我的大脑用过的。
来自喜欢函数式编程的人的热门观点,for 循环比缩减为新数组更具可读性
阅读这样的解决方案,我真的想知道人们是否曾经考虑过他们算法的空间/时间复杂度。 concat() 克隆数组,这意味着该算法不仅会像@JPdelaTorre 所指出的那样迭代每个元素,而且还会对每个其他元素进行迭代。有 100 万个项目(对于任何实际用例来说,这并不奇怪),这个算法在我的 PC 上运行需要将近 22 秒,而接受的答案需要 8 毫秒。去FP队!
a
adiga

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

Object.defineProperty(Array.prototype, 'chunk_inefficient', { value: function(chunkSize) { var array = this; return [].concat.apply([], array.map(function(elem, i) { return i % chunkSize ? [] : [array.slice(i, i + chunkSize)]; }) ); } }); console.log( [1, 2, 3, 4, 5, 6, 7].chunk_inefficient(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', { value: function(chunkSize) { var R = []; for (var i = 0; i < this.length; i += chunkSize) R.push(this.slice(i, i + chunkSize)); return 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]]

或者,如果您不想要 Array.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));
}});

或者

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

嗯,我会避免弄乱原型,因为在数组上调用 chunk 函数所获得的凉爽感并没有真正超过您添加的额外复杂性以及弄乱内置原型的细微错误可以引起。
他不是在搞乱它们,而是将它们扩展为数组。我知道永远不会接触 Object.prototype,因为这会冒泡到所有对象(一切),但是对于这个 Array 特定的函数,我没有看到任何问题。
很确定应该是 array.map(function(i) 而不是 array.map(function(elem,i)
基于 mozilla 开发网站上的兼容性图表,Array.map for IE9+。当心。
@rlemon 给你,这是导致的问题。请永远不要修改原生原型,尤其是没有供应商前缀的:developers.google.com/web/updates/2018/03/smooshgate 添加 array.myCompanyFlatten 很好,但请不要添加 array.flatten 并祈祷它永远不会引起问题。如您所见,mootools 多年前的决定现在影响了 TC39 标准。
C
Community

如果您不知道谁将使用您的代码(第 3 方、同事、以后的您自己等),请尽量避免使用原生原型,包括 Array.prototype

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

如果您有时间,请观看 Andrew Dupont 的 JSConf 2011 演讲,"Everything is Permitted: 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;

“避免使用原生原型”新的 js 开发人员应该得到一个临时的,如果不是永久的,这句话的纹身。
我多年来一直在使用 javascript,几乎没有时间花在原型上,在大多数调用函数上,从不像你看到的某些人那样进行修改。
我眼中最好的建议,最容易理解和实施的建议,非常感谢!
@JacobDalton 我认为这都是大学的错。人们认为 OOP 必须无处不在。所以他们害怕“只是创建一个功能”。他们希望确保将其放入某物内。即使它根本不合适。如果没有点符号,就没有“架构”。
@Gherman 我也经常看到这一点。我主要在 Laravel 工作,我店里的人倾向于创建各种经理类以“坚持”OOP,但这样做打破了 Laravel 的惯例,使项目变得更加复杂。
I
Ikechukwu Eze

使用生成器

function* chunks(arr, n) { for (let i = 0; i < arr.length; i += n) { yield arr.slice(i, i + n); } } let someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] console.log([...chunks(someArray, 2)]) // [[0, 1] , [2, 3], [4, 5], [6, 7], [8, 9]]


我对这个问题的所有答案感到惊讶,这些答案几乎都在使用生成器或以更复杂的方式使用它们。这个解决方案的简洁性和性能很好。
这是迄今为止最好的答案。
function* chunks<T>(arr: T[], n: number): Generator<T[], void> { 然后使用 const foo = [ ...chunks( bar, 4 ) ]; - @RayFoss
A
AymKdn

我在 jsperf.com 中测试了不同的答案。结果在此处可用:https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds

最快的功能(适用于 IE8)是这个:

function chunk(arr, chunkSize) {
  if (chunkSize <= 0) throw "Invalid chunk size";
  var R = [];
  for (var i=0,len=arr.length; i<len; i+=chunkSize)
    R.push(arr.slice(i,i+chunkSize));
  return R;
}

感谢@AymKdn 制定此基准:这非常有帮助!我使用的是 splice approach,它以 884432 的块大小使我的 Chrome v70 浏览器崩溃。使用您建议的“切片”方法,我的代码不会再使浏览器的“渲染”过程崩溃。 :)
这是它的打字稿版本:function chunk<T>(array: T[], chunkSize: number): T[][] { const R = []; for (let i = 0, len = array.length; i < len; i += chunkSize) R.push(array.slice(i, i + chunkSize)); return R; }
chunkSize = 0 需要多长时间?一些有效的函数输入不应停止进程。
@ceving 我刚刚在 chunkSize <= 0 时添加了一个条件
@AymKdn 我不确定,如果返回未修改的数组是最好的错误处理。函数的预期返回类型是 Array<Array>。并且非正的块大小没有任何意义。所以抛出错误对我来说似乎是合理的。
C
Charlton Provatas

ECMA 6 中的单行

const [list,chunkSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6]

[...Array(Math.ceil(list.length / chunkSize))].map(_ => list.splice(0,chunkSize))

它修改了原始的 list 数组
使用 .slice() 轻松修复.. .map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
在 JSPerf 上,这比许多其他答案的性能要高得多。
最好使用 [ ] 而不是 new Array()[...Array(Math.ceil(list.length / chuckSize)].map(_ => list.splice(0,chuckSize))
如果你在前面拼接,你也可以映射同一个数组本身:var split=(fields,record=2)=>\n fields.map((field,index,fields)=>\n fields.splice(index,record,fields.slice(index,record)));
A
Arek Flinik

我更喜欢使用 splice 方法:

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

必须小心这个拼接解决方案,因为它修改了原始数组,所以一定要清楚地记录副作用。
然后使用 slice 代替
@mplungjan 使用切片时,结果将一遍又一遍地成为相同的数组。因此,如果没有更多修改,它并不是真正的直接替代品。
我要添加到这个答案中的唯一内容是 clone 到原始数组。我会用 ES6 的扩展运算符来做到这一点。 var clone = [...array] 然后对克隆的数组进行长度检查和拼接。
或者,如果您不能使用 ES6 功能,您可以简单地 array = array.slice() 这也会创建一个浅拷贝。
G
George Herolyants

现在您可以使用 lodash 的 chunk 函数将数组拆分为更小的数组 https://lodash.com/docs#chunk 不再需要摆弄循环!


我觉得 SO javascript 问题应该有免责声明:你试过 lodash 吗?几乎是我在节点或浏览器中包含的第一件事。
r
rlemon

老问题:新答案!我实际上正在处理这个问题的答案,并让一个朋友改进它!所以这里是:

Array.prototype.chunk = function ( n ) {
    if ( !this.length ) {
        return [];
    }
    return [ this.slice( 0, n ) ].concat( this.slice(n).chunk(n) );
};

[1,2,3,4,5,6,7,8,9,0].chunk(3);
> [[1,2,3],[4,5,6],[7,8,9],[0]]

仅供参考,此方法的性能为 O(N^2),因此不应在对性能要求严格的代码部分或长数组中使用它(特别是当数组的 .length 远大于块大小时n)。如果这是一种惰性语言(与 javascript 不同),则该算法不会受到 O(N^2) 时间的影响。也就是说,递归实现很优雅。您可以修改它以提高性能,首先定义一个在 array,position 上递归的辅助函数,然后调度:Array.prototype.chunk 返回 [your helper function](...)
谢谢老师用你的精神祝福我,我今晚一定是有精神的
或... var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
S
Steve Holgado

有很多答案,但这是我使用的:

const chunk = (arr, size) =>
  arr
    .reduce((acc, _, i) =>
      (i % size)
        ? acc
        : [...acc, arr.slice(i, i + size)]
    , [])

// USAGE
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chunk(numbers, 3)

// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

首先,在将索引除以块大小时检查余数。

如果有余数,则返回累加器数组。

如果没有余数,则索引可被块大小整除,因此从原始数组中取出一个切片(从当前索引开始)并将其添加到累加器数组中。

因此,reduce 的每次迭代返回的累加器数组如下所示:

// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

很好的解决方案和很好的迭代视觉表示。我最终得到了一个非常相似的解决方案,我将其作为答案发布:stackoverflow.com/a/60779547
M
Matias Kinnunen

使用 Array.prototype.reduce() 的另一种解决方案:

const chunk = (array, size) => array.reduce((acc, _, i) => { if (i % size === 0) acc.push(array.slice(i, i + size)) 返回acc }, []) // 用法: const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] const chunked = chunk(numbers, 3) console.log(chunked)

此解决方案与 solution by Steve Holgado 非常相似。但是,由于此解决方案不使用数组扩展并且不在 reducer 函数中创建新数组,因此它比其他解决方案更快(参见 jsPerf test)并且主观上更具可读性(更简单的语法)。

在每次 nth 迭代(其中 n = size;从第一次迭代开始),累加器数组 (acc) 会附加一个数组块 ( array.slice(i, i + size)) 然后返回。在其他迭代中,累加器数组按原样返回。

如果 size 为零,则该方法返回一个空数组。如果 size 为负数,则该方法返回损坏的结果。因此,如果您的情况需要,您可能需要对负或非正 size 值做一些事情。

如果在您的情况下速度很重要,那么简单的 for 循环会比使用 reduce() 更快(请参阅 jsPerf test),并且有些人可能会发现这种样式也更具可读性:

function chunk(array, size) {
  // This prevents infinite loops
  if (size < 1) throw new Error('Size must be positive')

  const result = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

您的 reduce 示例是迄今为止最干净的方法
G
Gergely Fehérvári

我认为这是一个很好的 ES6 语法递归解决方案:

const chunk = function(array, size) { if (!array.length) { return []; } const head = array.slice(0, size); const tail = array.slice(size);返回[头,...块(尾,大小)]; }; console.log(chunk([1,2,3], 2));


u
user239558

好的,让我们从一个相当紧凑的开始:

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),[]);

因为当我们将 this 绑定到一个数字时一只小猫会死掉,所以我们可以像这样进行手动柯里化:

// 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);

在 iE8 中不起作用。
哈!我喜欢小猫的评论。抱歉没有额外的建设性意见:)
我会做(p[i/n|0] || (p[i/n|0] = [])),所以如果没有必要,你不要赋值......
对于 Currying(部分应用应用函数),您需要在示例 chunker.bind(null, 3) docs Function.prototype.bind() 中绑定 thisArg = null
n
nkitku

单线

const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));

对于打字稿

const chunk = <T>(arr: T[], size: number): T[][] =>
  [...Array(Math.ceil(arr.length / size))].map((_, i) =>
    arr.slice(size * i, size + size * i)
  );

演示

const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*一世)); document.write(JSON.stringify(chunk([1, 2, 3, 4], 2)));

按组数分块

const part=(a,n)=>[...Array(n)].map((_,i)=>a.slice(i*Math.ceil(a.length/n),(i+1)*Math.ceil(a.length/n)));

对于打字稿

const part = <T>(a: T[], n: number): T[][] => {
  const b = Math.ceil(a.length / n);
  return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};

演示

常量部分 = (a, n) => { 常量 b = Math.ceil(a.length / n); return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b)); }; document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6], 2))+'
'); document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6, 7], 2)));


谢谢! oneliner是最好的答案!
chunk([1,2,3,4],2) 产生 [ [ 1, 2 ], [ 3, 4 ], [] ]。对我来说似乎不合适。
无法重现您的结果@HansBouwmeeste。 u.davwheat.dev/3Om2Au5D.png
是的,但现在修好了,我应该提一下
@大卫惠特利。确认的。我尝试了最新版本,现在效果很好。
t
thoredge

我的目标是在纯 ES6 中创建一个简单的非变异解决方案。 javascript 的特殊性使得有必要在映射之前填充空数组:-(

function chunk(a, l) { 
    return new Array(Math.ceil(a.length / l)).fill(0)
        .map((_, n) => a.slice(n*l, n*l + l)); 
}

这个带有递归的版本看起来更简单,更引人注目:

function chunk(a, l) { 
    if (a.length == 0) return []; 
    else return [a.slice(0, l)].concat(chunk(a.slice(l), l)); 
}

ES6 荒谬的弱数组函数带来了很好的谜题:-)


我也写我的很像这样。如果您从 fill 中删除 0,它仍然有效,这会使 fill 看起来更合理,恕我直言。
A
A1rPun

为此 https://www.npmjs.com/package/array.chunk 创建了一个 npm 包

var result = [];

for (var i = 0; i < arr.length; i += size) {
  result.push(arr.slice(i, size + i));
}
return result;

使用 TypedArray

var result = [];

for (var i = 0; i < arr.length; i += size) {
  result.push(arr.subarray(i, size + i));
}
return result;

@A1rPun 我的错,我没有在那里添加评论。是的,TypedArray 没有 slice 方法,我们可以使用 subarray 代替 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
S
Sajeeb Ahamed

使用 Array.prototype.splice() 并拼接它,直到数组有元素。

Array.prototype.chunk = function(size) { let result = []; while(this.length) { result.push(this.splice(0, size)); } 返回结果; } 常量 arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];控制台.log(arr.chunk(2));

更新

Array.prototype.splice() 填充原始数组,执行 chunk() 后,原始数组 (arr) 变为 []

因此,如果您想保持原始数组不变,请将 arr 数据复制并保留到另一个数组中并执行相同的操作。

Array.prototype.chunk = function(size) { let data = [...this];让结果 = []; while(data.length) { result.push(data.splice(0, size)); } 返回结果; } 常量 arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log('chunked:', arr.chunk(2)); console.log('原始', arr);

PS:感谢@mts-knn 提及此事。


请注意,拼接会修改原始数组。如果您将 console.log(arr); 添加到代码片段的末尾,它将记录 [],即 arr 将是一个空数组。
u
user1460043

以下 ES2015 方法无需定义函数即可直接在匿名数组上工作(例如块大小为 2):

[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)

如果您想为此定义一个函数,您可以按如下方式进行(改进 K._ 对 Blazemonger's answer 的评论):

const array_chunks = (array, chunk_size) => array
    .map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
    .filter(x => x.length)

m
matsev

如果您使用 EcmaScript 版本 >= 5.1,则可以使用具有 O(N) 复杂度的 array.reduce() 实现 chunk() 的功能版本:

function chunk(chunkSize, array) { return array.reduce(function(previous, current) { var chunk; if (previous.length === 0 || previous[previous.length -1].length === chunkSize) { chunk = []; // 1 previous.push(chunk); // 2 } else { chunk = previous[previous.length -1]; // 3 } chunk.push(current); // 4 return previous; / /5}, []); // 6 } console.log(chunk(2, ['a', 'b', 'c', 'd', 'e'])); // 打印 [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]

对上述每个 // nbr 的解释:

如果先前的值,即先前返回的块数组为空,或者如果最后一个先前的块具有 chunkSize 项,则创建一个新块 将新块添加到现有块的数组中 否则,当前块是数组中的最后一个块of chunks 将当前值添加到 chunk 返回修改后的 chunks 数组 通过传递一个空数组来初始化归约

基于 chunkSize 的柯里化:

var chunk3 = function(array) {
    return chunk(3, array);
};

console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]

您可以将 chunk() 函数添加到全局 Array 对象:

Object.defineProperty(Array.prototype, 'chunk', { value: function(chunkSize) { return this.reduce(function(previous, current) { var chunk; if (previous.length === 0 || previous[previous. length -1].length === chunkSize) { chunk = []; previous.push(chunk); } else { chunk = previous[previous.length -1]; } chunk.push(current); return previous; } , []); } }); console.log(['a', 'b', 'c', 'd', 'e'].chunk(4)); // 打印 [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]


B
Bar Nuri

js

函数 splitToBulks(arr, bulkSize = 20) { const bulks = []; for (let i = 0; i < Math.ceil(arr.length / bulkSize); i++) { bulks.push(arr.slice(i * bulkSize, (i + 1) * bulkSize)); } 返回批量; } console.log(splitToBulks([1, 2, 3, 4, 5, 6, 7], 3));

打字稿

function splitToBulks<T>(arr: T[], bulkSize: number = 20): T[][] {
    const bulks: T[][] = [];
    for (let i = 0; i < Math.ceil(arr.length / bulkSize); i++) {
        bulks.push(arr.slice(i * bulkSize, (i + 1) * bulkSize));
    }
    return bulks;
}

M
Mihai Iorga
results = []
chunk_size = 10
while(array.length > 0){
   results.push(array.splice(0, chunk_size))
}

不知道为什么这被否决了,但代码可以使用一些解释。
因为拼接对原始数组具有破坏性。
m
metakungfu

纯javascript中的一行:

function chunks(array, size) { return Array.apply(0,{length: Math.ceil(array.length / size)}).map((_, index) => array.slice(index*size, (index +1)*size)) } // 下面将按 4 个字母对字母进行分组 console.log(chunks([...Array(26)].map((x,i)=>String.fromCharCode(i) + 97)), 4))


K
Karol Be

我建议使用 lodash。分块是那里许多有用的功能之一。指示:

npm i --save lodash

在您的项目中包括:

import * as _ from 'lodash';

用法:

const arrayOfElements = ["Element 1","Element 2","Element 3", "Element 4", "Element 5","Element 6","Element 7","Element 8","Element 9","Element 10","Element 11","Element 12"]
const chunkedElements = _.chunk(arrayOfElements, 10)

您可以在此处找到我的示例:https://playcode.io/659171/


R
Rein F

这是一个示例,其中我将数组拆分为 2 个元素的块,只需将块从数组中拼接出来,直到原始数组为空。

常量数组 = [86,133,87,133,88,133,89,133,90,133];常量 new_array = [];常量块大小 = 2; while (array.length) { const chunk = array.splice(0,chunksize); new_array.push(块); } console.log(new_array)


虽然这可能会回答问题,但一些解释会非常有帮助,请点击 edit 并输入一些解释。
A
Ayaz

您可以使用 Array.prototype.reduce 函数在一行中完成此操作。

让 arr = [1,2,3,4]; function chunk(arr, size) { let result = arr.reduce((rows, key, index) => (index % size == 0 ? rows.push([key]) : rows[rows.length-1]. push(key)) && 行, []);返回结果; } console.log(chunk(arr,2));


R
Redu

这将是我对这个话题的贡献。我想 .reduce() 是最好的方法。

var 段 = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r) : (r.push( [e]), r), []), arr = Array.from({length: 31}).map((_,i) => i+1);水库=段(arr,7); console.log(JSON.stringify(res));

但是上面的实现不是很有效,因为 .reduce() 贯穿所有 arr 函数。一种更有效的方法(非常接近于最快的命令式解决方案)是迭代缩减的(要分块的)数组,因为我们可以通过 Math.ceil(arr/n); 提前计算它的大小。一旦我们有了像 Array(Math.ceil(arr.length/n)).fill(); 这样的空结果数组,剩下的就是将 arr 数组的切片映射到其中。

function chunk(arr,n){ var r = Array(Math.ceil(arr.length/n)).fill();返回 r.map((e,i) => arr.slice(i*n, i*n+n)); } arr = Array.from({length: 31},(_,i) => i+1);水库=块(arr,7); console.log(JSON.stringify(res));

到目前为止一切顺利,但我们仍然可以进一步简化上面的代码片段。

var chunk = (a,n) => Array.from({length: Math.ceil(a.length/n)}, (_,i) => a.slice(i*n, i*n+n) ), arr = Array.from({length: 31},(_,i) => i+1), res = chunk(arr,7); console.log(JSON.stringify(res));


A
Arpit Jain
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 ] ]

a.splice(0, 2) 从 a 中移除 a[0..1] 的子数组并返回子数组 a[0..1]。我正在制作所有这些数组的数组
我建议使用非破坏性 slice() 方法而不是 splice()
M
Milind Chaudhary

使用来自 lodash 的块

lodash.chunk(arr,<size>).forEach(chunk=>{
  console.log(chunk);
})

K
Khaled Ayed -ngCode-

常量数组 = ['a', 'b', 'c', 'd', 'e'];常量大小 = 2;常量块 = []; while (array.length) { chunks.push(array.splice(0, size)); } 控制台日志(块);