将数组拆分为块

时间:2011-12-13 20:24:42

标签: javascript arrays split

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

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

什么方法适合将数组块(拆分)到许多较小的数组中,最多使用10个元素?

68 个答案:

答案 0 :(得分:507)

array.slice方法可以从数组的开头,中间或结尾提取切片,无需更改原始数组。

var i,j,temparray,chunk = 10;
for (i=0,j=array.length; i<j; i+=chunk) {
    temparray = array.slice(i,i+chunk);
    // do whatever
}

答案 1 :(得分:130)

根据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)];
            })
        );
    }
});

演示:

> [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的方法相同,这就是为什么我最初没有提交这个答案):

更有效的方法:

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;
    }
});
// refresh page if experimenting and you already defined Array.prototype.chunk

现在我的首选方式是以上或以下之一:

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

答案 2 :(得分:83)

如果您不知道谁会消耗您的代码(第三方,同事,您自己以后等),请尽量避免使用本机原型(包括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;

答案 3 :(得分:65)

这是使用reduce

的ES6版本
perChunk = 2 // items per chunk    

inputArray = ['a','b','c','d','e']

inputArray.reduce((resultArray, item, index) => { 
  const chunkIndex = Math.floor(index/perChunk)

  if(!resultArray[chunkIndex]) {
    resultArray[chunkIndex] = [] // start a new chunk
  }

  resultArray[chunkIndex].push(item)

  return resultArray
}, [])

// result: [['a','b'], ['c','d'], ['e']]

您已准备好进一步链接地图/减少变换。 您的输入数组保持不变

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

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

答案 4 :(得分:32)

我在jsperf.com上测试了不同的答案。结果可在那里找到:http://jsperf.com/chunk-mtds

最快的功能(和IE8一样)就是这个:

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

答案 5 :(得分:27)

我更喜欢使用splice方法:

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

答案 6 :(得分:25)

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

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]]

答案 7 :(得分:24)

ECMA 6中的单行

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

new Array(Math.ceil(list.length / chuckSize)).fill().map(_ => list.splice(0,chuckSize))

答案 8 :(得分:21)

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

答案 9 :(得分:16)

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

const chunk = (arr, size) => (
  arr.reduce((acc, _, i) => {
    if (i % size === 0) acc.push(arr.slice(i, i + size))
    return acc
  }, [])
)

// Usage:
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)和主观可读性(语法更简单)。

在每 n 次迭代中(其中 n = size;从第一次迭代开始),附加累加器数组(acc)与数组的一部分(arr.slice(i, i + size))一起返回。在其他迭代中,累加器数组按原样返回。

如果size为零,则该方法返回一个空数组。如果size为负,则该方法返回无效结果。因此,如果需要,您可能需要对负size值或负for进行一些处理。


如果在您的情况下速度很重要,那么简单的arr.reduce()循环将比使用function chunk(arr, size) { // This prevents infinite loops if (size < 1) throw new Error('Size must be positive') const result = [] for (let i = 0; i < arr.length; i += size) { result.push(arr.slice(i, i + size)) } return result } (请参见jsPerf test)更快,并且有些人可能还会发现这种样式更易读:

{{1}}

答案 10 :(得分:13)

好的,让我们从相当紧张的开始:

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

答案 11 :(得分:9)

我的目标是在纯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奇怪的弱阵列功能带来了很好的难题: - )

答案 12 :(得分:9)

我认为这是使用ES6语法的不错的递归解决方案:

const chunk = function(array, size) {
  if (!array.length) {
    return [];
  }
  const head = array.slice(0, size);
  const tail = array.slice(size);

  return [head, ...chunk(tail, size)];
};

console.log(chunk([1,2,3], 2));

答案 13 :(得分:7)

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

file = open(os.path.join(direct, "Test.txt"),'r')
print(file.read())

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

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

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

因此,每次reduce的迭代返回的累加器数组看起来像这样:

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]]

答案 14 :(得分:7)

使用Array.prototype.splice()并对其进行拼接,直到数组具有元素为止。

Array.prototype.chunk = function(size) {
    let result = [];
    
    while(this.length) {
        result.push(this.splice(0, size));
    }
        
    return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.chunk(2));

更新

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

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

Array.prototype.chunk = function(size) {
  let data = [...this];  
  let result = [];
    
    while(data.length) {
        result.push(data.splice(0, size));
    }

    return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log('chunked:', arr.chunk(2));
console.log('original', arr);

P.S:感谢@ mts-knn提到此事。

答案 15 :(得分:7)

如果您使用EcmaScript版本&gt; = 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']));
// prints [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]

上述每个// nbr的说明:

  1. 如果先前的值(即先前返回的块数组)为空或者上一个上一个块具有chunkSize个项目
  2. ,则创建一个新块
  3. 将新块添加到现有块的数组
  4. 否则,当前块是块数组中的最后一个块
  5. 将当前值添加到块
  6. 返回已修改的块数组
  7. 通过传递空数组
  8. 来初始化减少量

    基于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));
    // prints [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]
    

答案 16 :(得分:7)

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

答案 17 :(得分:7)

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 ] ]

答案 18 :(得分:5)

为此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;

答案 19 :(得分:5)

这将是我对这个主题的贡献。我猜.reduce()是最好的方式。

var segment = (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);
        res = segment(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();
  return r.map((e,i) => arr.slice(i*n, i*n+n));
}

arr = Array.from({length: 31},(_,i) => i+1);
res = chunk(arr,7);
console.log(JSON.stringify(res));

答案 20 :(得分:5)

    const array = [86,133,87,133,88,133,89,133,90,133];
    const new_array = [];

	const chunksize = 2;
    while (array.length) {
    	const chunk = array.splice(0,chunksize);
    	new_array.push(chunk);
    }

    console.log(new_array)

答案 21 :(得分:4)

基于Array.prototype reducepush方法的ES6单行方法:

const doChunk = (list, size) => list.reduce((r, v) =>
  (!r.length || r[r.length - 1].length === size ?
    r.push([v]) : r[r.length - 1].push(v)) && r
, []);

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

答案 22 :(得分:4)

纯javascript中的一行:

function chunks(array, size) {
  return Array.apply(0,{length: Math.ceil(array.length / size)}).map((_, index) => array.slice(index*size, (index+1)*size))
}

// The following will group letters of the alphabet by 4
console.log(chunks([...Array(26)].map((x,i)=>String.fromCharCode(i + 97)), 4))

答案 23 :(得分:4)

你可以把这个ES6的chunk函数拿来,好用:

const chunk = (array, size) =>
  Array.from({length: Math.ceil(array.length / size)}, (value, index) => array.slice(index * size, index * size + size));

const itemsPerChunk = 3;
const inputArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

const newArray = chunk(inputArray, itemsPerChunk);
console.log(newArray.length); // 3,

document.write(JSON.stringify(newArray)); //  [ [ 'a', 'b', 'c' ], [ 'd', 'e', 'f' ], [ 'g' ] ]

答案 24 :(得分:3)

ES6 Generator

function* chunkArray(array,size=1){
    var clone = array.slice(0);
    while (clone.length>0) 
      yield clone.splice(0,size); 
};
var a = new Array(100).fill().map((x,index)=>index);
for(const c of chunkArray(a,10)) 
    console.log(c);

答案 25 :(得分:3)

使用发电机

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]
[...chunks(someArray, 2)] // [[0,1],[2,3],[4,5],[6,7],[8,9]]

答案 26 :(得分:3)

我建议使用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/

答案 27 :(得分:3)

这是我能想到的最有效,最直接的解决方案:

function chunk(array, chunkSize) {
    let chunkCount = Math.ceil(array.length / chunkSize);
    let chunks = new Array(chunkCount);
    for(let i = 0, j = 0, k = chunkSize; i < chunkCount; ++i) {
        chunks[i] = array.slice(j, k);
        j = k;
        k += chunkSize;
    }
    return chunks;
}

答案 28 :(得分:2)

如果您使用的是Underscore JS,则只需使用:

var result = _.chunk(arr,elements_per_chunk)

无论如何,大多数项目已经使用下划线作为依赖项。

答案 29 :(得分:2)

以下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)

答案 30 :(得分:2)

单行

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

OR

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

对于TypeScript

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

演示

const chunk = (a,n)=>[...Array(-~(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
document.write(JSON.stringify(chunk(arr, 2)));

答案 31 :(得分:2)

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

adjust_first_column <- function(matrix) {
rownames(matrix) <- matrix[,1]
adjustedMatrix <- matrix[,-1]
return(adjustedMatrix)
}

答案 32 :(得分:2)

编辑:@ mblase75在写我的时候为早期的答案添加了更简洁的代码,所以我建议继续使用他的解决方案。

你可以使用这样的代码:

var longArray = ["Element 1","Element 2","Element 3", /*...*/];
var smallerArrays = []; // will contain the sub-arrays of 10 elements each
var arraySize = 10;
for (var i=0;i<Math.ceil(longArray.length/arraySize);i++) {
    smallerArrays.push(longArray.slice(i*arraySize,i*arraySize+arraySize));
}

更改arraySize的值以更改较小数组的最大长度。

答案 33 :(得分:2)

这是一个仅使用递归和slice()的非变异解决方案。

const splitToChunks = (arr, chunkSize, acc = []) => (
    arr.length > chunkSize ?
        splitToChunks(
            arr.slice(chunkSize),
            chunkSize,
            [...acc, arr.slice(0, chunkSize)]
        ) :
        [...acc, arr]
);

然后只需使用splitToChunks([1, 2, 3, 4, 5], 3)来获取[[1, 2, 3], [4, 5]]

以下是您试用的小提琴:https://jsfiddle.net/6wtrbx6k/2/

答案 34 :(得分:1)

这里是整洁的优化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);

答案 35 :(得分:1)

js

function 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));
    }
    return bulks;
}

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;
}

答案 36 :(得分:1)

示例 不变的源数组
并且一次制作所有的块。 (内存保护程序!)

const array = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21];

const chunkSize = 4
for (var i = 0; i < array.length; i += chunkSize) {
    const chunk = array.slice(i, i + chunkSize);
    console.log('chunk=',chunk)
    // do whatever
}
console.log('src array didnt changed. array=',array)

答案 37 :(得分:1)

晚了,这是我的两分钱。就像很多人说的,我首先会想到类似的东西

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

说明

  1. 常见的答案将首先确定块的数量,然后根据块所在的位置和每个块的大小获取原始数组的切片

  2. chunker reducer 函数将遍历每个元素并将其放入相应评估块的数组中。

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

PS:reduce(ing) 的优势在于可以轻松更改分组标准。在问题和示例中,标准是相邻单元格(并且映射使用切片)。但是您可能希望在“循环”中执行此操作,例如使用 mod(% 运算符)或任何其他数学公式

重新阅读它让我发现公式也可以是一个参数,从而得到一个更通用的解决方案并需要 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 也可用于创建命名数组又名对象,函数返回字符串而不是数字:)

答案 38 :(得分:1)

我稍微改变了BlazeMonger以用于jQuery对象..

var $list = $('li'),
    $listRows = [];


for (var i = 0, len = $list.length, chunk = 4, n = 0; i < len; i += chunk, n++) {
   $listRows[n] = $list.slice(i, i + chunk);
}

答案 39 :(得分:1)

如果这对任何人都有用,则可以在RxJS 6中非常简单地完成此操作:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
from(arr).pipe(bufferCount(3)).subscribe(chunk => console.log(chunk));

输出:[1、2、3] [4、5、6] [7、8、9] [10、11、12] [13、14、15] [16]

答案 40 :(得分:1)

我创建了以下 JSFiddle 来演示我对您问题的处理方法。

&#13;
&#13;
(function() {
  // Sample arrays
  var //elements = ["0", "1", "2", "3", "4", "5", "6", "7"],
      elements = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43"];

  var splitElements = [],
      delimiter = 10; // Change this value as needed
      
  // parameters: array, number of elements to split the array by
  if(elements.length > delimiter){
  	splitElements = splitArray(elements, delimiter);
  }
  else {
  	// No need to do anything if the array's length is less than the delimiter
  	splitElements = elements;
  }
  
  //Displaying result in console
  for(element in splitElements){
  	if(splitElements.hasOwnProperty(element)){
    	console.log(element + " | " + splitElements[element]);
    }
  }
})();

function splitArray(elements, delimiter) {
  var elements_length = elements.length;

  if (elements_length > delimiter) {
    var myArrays = [], // parent array, used to store each sub array
      first = 0, // used to capture the first element in each sub array
      index = 0; // used to set the index of each sub array

    for (var i = 0; i < elements_length; ++i) {
      if (i % delimiter === 0) {
      	// Capture the first element of each sub array from the original array, when i is a modulus factor of the delimiter.
        first = i;
      } else if (delimiter - (i % delimiter) === 1) {
      // Build each sub array, from the original array, sliced every time the i one minus the modulus factor of the delimiter.
        index = (i + 1) / delimiter - 1;
        myArrays[index] = elements.slice(first, i + 1);
      }
      else if(i + 1 === elements_length){
      	// Build the last sub array which contain delimiter number or less elements
      	myArrays[index + 1] = elements.slice(first, i + 1);
      }
    }
    // Returned is an array of arrays
    return myArrays;
  }
}
&#13;
&#13;
&#13;

首先,我有两个例子:一个少于八个元素的数组,另一个带有八个以上元素的数组(注释你不想使用的那个)。

然后我检查数组的大小,简单但必不可少,以避免额外的计算。从此处如果数组符合条件(数组大小&gt; delimiter),我们将进入splitArray函数。

splitArray函数接受分隔符(意思是8,因为这是你想要拆分的)和数组本身。由于我们正在重复使用数组长度,因此我将其缓存在变量中,以及firstlast

first表示数组中第一个元素的位置。该数组是由8个元素组成的数组。因此,为了确定第一个元素,我们使用 modulus operator

myArrays是数组数组。在其中,我们将在每个索引处存储任何大小为8或更小的子数组。这是下面算法的关键策略。

index表示myArrays变量的索引。每次要存储8个或更少元素的子数组时,需要将其存储在相应的索引中。因此,如果我们有27个元素,那意味着4个数组。第一,第二和第三阵列各有8个元素。最后一个只有3个元素。因此index将分别为0,1,2和3。

棘手的部分只是简单地计算出数学并尽可能地优化它。例如else if (delimiter - (i % delimiter) === 1)这是为了找到阵列中应该进入的最后一个元素,当一个数组已满(例如:包含10个元素)。

此代码适用于每种情况,您甚至可以更改delimiter以匹配您希望获得的任何数组大小。非常好的权利: - )

有任何问题吗?请随时在下面的评论中提问。

答案 41 :(得分:1)

我刚刚在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));

答案 42 :(得分:1)

这是我使用Coffeescript列表理解的方法。详细说明Coffeescript中的理解能力的文章可以是found here

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

答案 43 :(得分:1)

这就是我使用的方法,它可能不会很快,但它既紧凑又简单:

let chunksplit = (stream, size) => stream.reduce((chunks, item, idx, arr) => (idx % size == 0) ? [...chunks, arr.slice(idx, idx + size)] : chunks, []);
//if the index is a multiple of the chunksize, add new array

let testArray = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22];

document.write(JSON.stringify( chunksplit(testArray, 5) ));
//using JSON.stringify for the nested arrays to be shown

答案 44 :(得分:1)

使用lodash中的块

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

答案 45 :(得分:1)

这是一个尾部调用优化的递归解决方案。

const splitEvery = (n, xs, y=[]) =>
  xs.length===0 ? y : splitEvery(n, xs.slice(n), y.concat([xs.slice(0, n)])) 

console.log(splitEvery(2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))

答案 46 :(得分:1)

这应该是简单明了的答案,没有很多数学上的复杂性。

function chunkArray(array, sizeOfTheChunkedArray) {
  const chunked = [];

  for (let element of array) {
    const last = chunked[chunked.length - 1];

    if(!last || last.length === sizeOfTheChunkedArray) {
      chunked.push([element])
    } else {
      last.push(element);
    }
  }
  return chunked;
}

答案 47 :(得分:1)

ES6传播功能性#ohmy #ftw

const chunk =
  (size, xs) => 
    xs.reduce(
      (segments, _, index) =>
        index % size === 0 
          ? [...segments, xs.slice(index, index + size)] 
          : segments, 
      []
    );

console.log( chunk(3, [1, 2, 3, 4, 5, 6, 7, 8]) );

答案 48 :(得分:1)

嗨,试试看-

 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)

答案 49 :(得分:0)

对于功能性解决方案,请使用Ramda

popularProducts是您的输入数组,5是块大小

&#13;
&#13;
import splitEvery from 'ramda/src/splitEvery'

splitEvery(5, popularProducts).map((chunk, i) => {
// do something with chunk

})
&#13;
&#13;
&#13;

答案 50 :(得分:0)

尝试一下:

var oldArray =  ["Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango"];

var newArray = [];

while(oldArray.length){
    let start = 0;
    let end = 10;
    newArray.push(oldArray.slice(start, end));
    oldArray.splice(start, end);
 }
 
 console.log(newArray);

答案 51 :(得分:0)

const array = ['a', 'b', 'c', 'd', 'e'];
const size = 2;
const chunks = [];
while(array.length) {
  chunks.push(array.splice(0,size));
}
console.log(chunks);

答案 52 :(得分:0)

TypeScript 版本。演示的是 101 个随机 uid 分成 10 个一组

const idArrayLengthLimit = 10;
const randomOneHundredOneIdArray = Array
    .from(Array(101).keys())
    .map(() => generateUid(5));

function generateUid(length: number) {
  const uidString: string[] = [];
  const uidChars = 'abcdefghijklmnopqrstuvwxyz0123456789';
  for (let i = 0; i < length; i++) {
    uidString
      .push(uidChars.charAt(Math.floor(Math.random() * uidChars.length)));
  }
  return uidString.join('');
}

for (let i = 0; i < randomOneHundredOneIdArray.length; i++) {
 if(i % idArrayLengthLimit === 0){
     const result = randomOneHundredOneIdArray
       .filter((_,id) => id >= i && id < i + idArrayLengthLimit);
    // Observe result
    console.log(result);
 }
}

答案 53 :(得分:0)

# in coffeescript
# assume "ar" is the original array
# newAr is the new array of arrays

newAr = []
chunk = 10
for i in [0... ar.length] by chunk
   newAr.push ar[i... i+chunk]

# or, print out the elements one line per chunk
for i in [0... ar.length] by chunk
   console.log ar[i... i+chunk].join ' '

答案 54 :(得分:0)

我更喜欢使用拼接方法而不是切片。 该解决方案使用数组的长度和块大小来创建循环计数,然后循环遍历该数组,该数组由于每次拼接都在每次操作后变小。

    function chunk(array, size) {
      let resultArray = [];
      let chunkSize = array.length/size;
      for(i=0; i<chunkSize; i++) {
        resultArray.push(array.splice(0, size));
      }
    return console.log(resultArray);
    }
    chunk([1,2,3,4,5,6,7,8], 2);

如果您不想突变原始数组,则可以使用传播运算符克隆原始数组,然后使用该数组解决问题。

    let clonedArray = [...OriginalArray]

答案 55 :(得分:0)

聚会太晚了,但我使用.join("")将数组转换为一个巨大的字符串,然后使用正则表达式将其.match(/.{1,7}/)转换为最大长度的子字符串数组的方法解决了类似的问题7.

const arr = ['abc', 'def', 'gh', 'ijkl', 'm', 'nopq', 'rs', 'tuvwx', 'yz'];
const arrayOfSevens = arr.join("").match(/.{1,7}/g);
// ["abcdefg", "hijklmn", "opqrstu", "vwxyz"]

看看它在与其他方法的速度测试中的表现会很有趣

答案 56 :(得分:0)

我这样解决了:

const chunks = [];
const chunkSize = 10;
for (let i = 0; i < arrayToSplit.length; i += chunkSize) {
  const tempArray = arrayToSplit.slice(i, i + chunkSize);
  chunks.push(tempArray);
}

答案 57 :(得分:0)

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

远离最快的性能,但是我很高兴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]]

答案 58 :(得分:0)

这是使用reduce()方法的另一种解决方案,但与其他示例略有不同。希望我的解释也更加清晰。

var arr = [0, 1, 2, 3, 4, 5, 6, 7];
var chunkSize = 3;

arr = arr.reduce((acc, item, idx) => {
  let group = acc.pop();
  if (group.length == chunkSize) {
    acc.push(group);
    group = [];
  }
  group.push(item);
  acc.push(group);
  return acc;
}, [[]]);

console.log(arr); //Prints [[0, 1, 2], [3, 4, 5], [6, 7]]

解释

我们调用一个reducer,对于数组中的每个项,它使用pop()获取累加器的最后一项。请记住,此项目是一个数组,其中最多可包含chunkSize个项目(在此示例中 3 )。

当且仅当此组的数组长度等于chunksize时,我们需要将该组重新插入累加器并创建一个新组。

然后,我们将当前item推送到我们的group数组(,其中可能已包含前一步骤中的0,1或2项)。将当前item插入group后,我们需要将group重新插入较大的集合中。

此过程将重复,直到我们遍历arr中的所有项目。

请注意,我们还为reducer提供了一个带有[[]]的数组中空数组的起始值。

答案 59 :(得分:0)

这是使用ImmutableJS的解决方案,其中items是不可变列表,size是所需的分组大小。

const partition = ((items, size) => {
  return items.groupBy((items, i) => Math.floor(i/size))
})

答案 60 :(得分:0)

对此问题可能有很多解决方案。

我的最爱之一是:

function chunk(array, size) {
    const chunked = [];

    for (element of array){
        let last = chunked[chunked.length - 1];

        if(last && last.length != size){
            last.push(element)
        }else{
            chunked.push([element])
        }
    }
   
    return chunked;
}


function chunk1(array, size) {
    const chunked = [];

    let index = 0;

    while(index < array.length){
        chunked.push(array.slice(index,index+ size))
        index += size;
    }
    return chunked;
}

console.log('chunk without slice:',chunk([1,2,3,4,5,5],2));
console.log('chunk with use of slice funtion',chunk1([1,2,3,4,5,6],2))

答案 61 :(得分:0)

她是使用@Blazemonger解决方案的简单解决方案

function array_chunk(arr, size){
    // initialize vars
    var i,
    j = arr.length,
    tempArray = [];
    // loop through and jump based on size
    for (i=0; i<j; i+=size) {
        // slice chunk of arr and push to tempArray
        tempArray.push(arr.slice(i,i+size));
    }
    // return temp array (chunck)
    return tempArray
}

这让我的管道流动,希望这有助于其他人。 :)

答案 62 :(得分:0)

我的技巧是使用parseInt(i/chunkSize)parseInt(i%chunkSize)然后填充数组

// filling items
let array = [];
for(let i = 0; i< 543; i++)
  array.push(i);
 
 // printing the splitted array
 console.log(getSplittedArray(array, 50));
 
 // get the splitted array
 function getSplittedArray(array, chunkSize){
  let chunkedArray = [];
  for(let i = 0; i<array.length; i++){
    try{
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];
    }catch(e){
      chunkedArray[parseInt(i/chunkSize)] = [];
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];
    }
  }
  return chunkedArray;
 }

答案 63 :(得分:-1)

嗯,一个很好的功能是:

function chunk(arr,times){
    if(times===null){var times = 10} //Fallback for users wanting to use the default of ten
   var tempArray = Array() //Array to be populated with chunks
    for(i=0;i<arr.length/times;i++){
     tempArray[i] = Array() //Sub-Arrays        //Repeats for each chunk         
   for(j=0;j<times;j++){
        if(!(arr[i*times+j]===undefined)){tempArray[i][j] = arr[i*times+j]//Populate Sub-  Arrays with chunks
    }
     else{
       j = times //Stop loop
       i = arr.length/times //Stop loop
  }
    }
     }
   return tempArray //Return the populated and chunked array
   }

用法是:

chunk(array,sizeOfChunks)

我对此进行了评论,以便您了解发生了什么。

(格式有点偏,我在手机上编程了这个)

答案 64 :(得分:-1)

function chunk(arr, size) {
  var tempAr = [];
  var j=  0;
  for(var i =0 ;i<arr.length;i++){ 
    if(j==size || j==0){  
     tempAr.push(arr.slice(i,(i+size)));
      j=0;
      }j++;
  }
  return tempAr;
}

答案 65 :(得分:-1)

Neat and clean easy to understand

 let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
 let len = nums.length ;

    const chunkArr = (arr, chunkNo) => {
      let newArr = [];
      for(let i = 0; i < len; i++){
        if(nums[0] !== "" && nums[0] !== undefined ){
          let a = nums.splice(0,chunkNo) ; 
          newArr.push(a);
        }
      }
       return newArr ;
    }
    console.log(chunkArr(nums, 5));

答案 66 :(得分:-1)

Array.prototype.sliceIntoChunks = function(chunkSize) {
                    var chunks = [];
                    var temparray = null;

                    for (var i = 0; i < this.length; i++) {
                        if (i % chunkSize === 0) {
                            temparray = new Array();
                            chunks.push(temparray);
                        }
                        temparray.push(this[i]);
                    }

                    return chunks;
                };

您可以按如下方式使用:

var myArray = ["A", "B", "C", "D", "E"];
var mySlicedArray = myArray.sliceIntoChunks(2);

结果:

mySlicedArray[0] = ["A", "B"];
mySlicedArray[1] = ["C", "D"];
mySlicedArray[2] = ["E"];

答案 67 :(得分:-1)

  

出于相同的目的,我使用了以下方法,该方法对我来说非常有效。希望这对某人有帮助

private byte[][] ByteArrayToChunks(byte[] byteData, long BufferSize)
{
    byte[][] chunks = byteData.Select((value, index) => new { PairNum = Math.Floor(index / (double)BufferSize), value }).GroupBy(pair => pair.PairNum).Select(grp => grp.Select(g => g.value).ToArray()).ToArray();
    return chunks;
}