Tengo una variedad de correos electrónicos (puede ser solo 1 correo electrónico o 100 correos electrónicos) y necesito enviar la matriz con una solicitud ajax (que sé cómo hacerlo), pero solo puedo enviar una matriz que tiene 10 o menos correos electrónicos en él. Entonces, si hay una matriz original de 20 correos electrónicos, tendré que dividirlos en 2 matrices de 10 cada una. o si hay 15 correos electrónicos en la matriz original, luego 1 matriz de 10 y otra matriz de 5. Estoy usando jQuery, ¿cuál sería la mejor manera de hacer esto?
fuente
var size = 10; var arrayOfArrays = []; for (var i=0; i<bigarray.length; i+=size) { arrayOfArrays.push(bigarray.slice(i,i+size)); } console.log(arrayOfArrays);
A diferencia de
splice()
,slice()
no es destructivo para la matriz original.fuente
Simplemente recorra la matriz, uniéndola hasta que se consuma por completo.
var a = ['a','b','c','d','e','f','g'] , chunk while (a.length > 0) { chunk = a.splice(0,3) console.log(chunk) }
salida
[ 'a', 'b', 'c' ] [ 'd', 'e', 'f' ] [ 'g' ]
fuente
Puede usar lodash: https://lodash.com/docs
_.chunk(['a', 'b', 'c', 'd'], 2); // → [['a', 'b'], ['c', 'd']]
fuente
Suponiendo que no desea destruir la matriz original, puede usar un código como este para dividir la matriz larga en matrices más pequeñas sobre las que luego puede iterar:
var longArray = []; // assume this has 100 or more email addresses in it var shortArrays = [], i, len; for (i = 0, len = longArray.length; i < len; i += 10) { shortArrays.push(longArray.slice(i, i + 10)); } // now you can iterate over shortArrays which is an // array of arrays where each array has 10 or fewer // of the original email addresses in it for (i = 0, len = shortArrays.length; i < len; i++) { // shortArrays[i] is an array of email addresss of 10 or less }
fuente
Otra implementación:
const arr = ["H", "o", "w", " ", "t", "o", " ", "s", "p", "l", "i", "t", " ", "a", " ", "l", "o", "n", "g", " ", "a", "r", "r", "a", "y", " ", "i", "n", "t", "o", " ", "s", "m", "a", "l", "l", "e", "r", " ", "a", "r", "r", "a", "y", "s", ",", " ", "w", "i", "t", "h", " ", "J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]; const size = 3; const res = arr.reduce((acc, curr, i) => { if ( !(i % size) ) { // if index is 0 or can be divided by the `size`... acc.push(arr.slice(i, i + size)); // ..push a chunk of the original array to the accumulator } return acc; }, []); // => [["H", "o", "w"], [" ", "t", "o"], [" ", "s", "p"], ["l", "i", "t"], [" ", "a", " "], ["l", "o", "n"], ["g", " ", "a"], ["r", "r", "a"], ["y", " ", "i"], ["n", "t", "o"], [" ", "s", "m"], ["a", "l", "l"], ["e", "r", " "], ["a", "r", "r"], ["a", "y", "s"], [",", " ", "w"], ["i", "t", "h"], [" ", "J", "a"], ["v", "a", "S"], ["c", "r", "i"], ["p", "t"]]
NB: esto no modifica la matriz original.
O, si prefiere un método funcional, 100% inmutable (aunque realmente no hay nada malo en mutar en un lugar como se hizo anteriormente) y autónomo:
function splitBy(size, list) { return list.reduce((acc, curr, i, self) => { if ( !(i % size) ) { return [ ...acc, self.slice(i, i + size), ]; } return acc; }, []); }
fuente
Como complemento de la respuesta de @ jyore , y en caso de que aún desee mantener la matriz original:
var originalArray = [1,2,3,4,5,6,7,8]; var splitArray = function (arr, size) { var arr2 = arr.slice(0), arrays = []; while (arr2.length > 0) { arrays.push(arr2.splice(0, size)); } return arrays; } splitArray(originalArray, 2); // originalArray is still = [1,2,3,4,5,6,7,8];
fuente
Array.reduce podría ser ineficaz para arreglos grandes, especialmente con el operador mod. Creo que una solución funcional más limpia (y posiblemente más fácil de leer) sería esta:
const chunkArray = (arr, size) => arr.length > size ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)] : [arr];
fuente
Otro método:
var longArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var size = 2; var newArray = new Array(Math.ceil(longArray.length / size)).fill("") .map(function() { return this.splice(0, size) }, longArray.slice()); // newArray = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]];
Esto no afecta a la matriz original, ya que una copia, realizada con un segmento, se pasa al argumento "este" del mapa.
fuente
También me gustaría compartir mi solución. Es un poco más detallado, pero también funciona.
var data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; var chunksize = 4; var chunks = []; data.forEach((item)=>{ if(!chunks.length || chunks[chunks.length-1].length == chunksize) chunks.push([]); chunks[chunks.length-1].push(item); }); console.log(chunks);
Salida (formateada):
[ [ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12], [13, 14, 15 ] ]
fuente
Otra implementación, usando Array.reduce (¡creo que es la única que falta!):
const splitArray = (arr, size) => { if (size === 0) { return []; } return arr.reduce((split, element, index) => { index % size === 0 ? split.push([element]) : split[Math.floor(index / size)].push(element); return split; }, []); };
Como muchas de las soluciones anteriores, esta no es destructiva. Devolver una matriz vacía cuando el tamaño es 0 es solo una convención. Si
if
se omite el bloque, obtendrá un error, que podría ser lo que desea.fuente
Puedes echar un vistazo a este código. Simple y efectivo.
function chunkArrayInGroups(array, unit) { var results = [], length = Math.ceil(array.length / unit); for (var i = 0; i < length; i++) { results.push(array.slice(i * unit, (i + 1) * unit)); } return results; } chunkArrayInGroups(["a", "b", "c", "d"], 2);
fuente
Aquí hay un trazador de líneas simple
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); console.log(segment(arr,7));
fuente
Mas Compacto:
const chunk = (xs, size) => xs.map((_, i) => (i % size === 0 ? xs.slice(i, i + size) : null)).filter(Boolean); // Usage: const sampleArray = new Array(33).fill(undefined).map((_, i) => i); console.log(chunk(sampleArray, 5));
fuente
Si desea un método que no modifique la matriz existente, intente esto:
let oldArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; let newArray = []; let size = 3; // Size of chunks you are after let j = 0; // This helps us keep track of the child arrays for (var i = 0; i < oldArray.length; i++) { if (i % size === 0) { j++ } if(!newArray[j]) newArray[j] = []; newArray[j].push(oldArray[i]) }
fuente
function chunkArrayInGroups(arr, size) { var newArr=[]; for (var i=0; arr.length>size; i++){ newArr.push(arr.splice(0,size)); } newArr.push(arr.slice(0)); return newArr; } chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);
fuente
function chunkArrayInGroups(arr, size) { var newArr=[]; for (var i=0; i < arr.length; i+= size){ newArr.push(arr.slice(i,i+size)); } return newArr; } chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6], 3);
fuente
como una función
var arrayChunk = function (array, chunkSize) { var arrayOfArrays = []; if (array.length <= chunkSize) { arrayOfArrays.push(array); } else { for (var i=0; i<array.length; i+=chunkSize) { arrayOfArrays.push(array.slice(i,i+chunkSize)); } } return arrayOfArrays; }
usar
arrayChunk(originalArray, 10) //10 being the chunk size.
fuente
usando recursividad
let myArr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]; let size = 4; //Math.sqrt(myArr.length); --> For a n x n matrix let tempArr = []; function createMatrix(arr, i) { if (arr.length !== 0) { if(i % size == 0) { tempArr.push(arr.splice(0,size)) } createMatrix(arr, i - 1) } } createMatrix(myArr, myArr.length); console.log(tempArr);
Nota: La matriz existente, es decir, myArr, se modificará.
fuente
usando el prototipo podemos configurarlo directamente en la clase de matriz
Array.prototype.chunk = function(n) { if (!this.length) { return []; } return [this.slice(0, n)].concat(this.slice(n).chunk(n)); }; console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].chunk(5));
fuente
const originalArr = [1,2,3,4,5,6,7,8,9,10,11]; const splittedArray = []; while (originalArr.length > 0) { splittedArray.push(originalArr.splice(0,range)); }
salida para rango 3
splittedArray === [[1,2,3][4,5,6][7,8,9][10,11]]
salida para rango 4
splittedArray === [[1,2,3,4][5,6,7,8][9,10,11]]
fuente