Come dividere un array lungo in array più piccoli, con JavaScript


100

Ho un array di e-mail (può essere solo 1 e-mail o 100 e-mail) e devo inviare l'array con una richiesta ajax (che so come fare), ma posso inviare solo un array che ha 10 o meno e-mail in esso. Quindi, se esiste un array originale di 20 e-mail, dovrò dividerli in 2 array di 10 ciascuno. o se ci sono 15 e-mail nell'array originale, quindi 1 array di 10 e un altro array di 5. Sto usando jQuery, quale sarebbe il modo migliore per farlo?

Risposte:


195

Non usare jquery ... usa javascript semplice

var a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];

var b = a.splice(0,10);

//a is now [11,12,13,14,15];
//b is now [1,2,3,4,5,6,7,8,9,10];

Puoi eseguire il loop per ottenere il comportamento che desideri.

var a = YOUR_ARRAY;
while(a.length) {
    console.log(a.splice(0,10));
}

Questo ti darebbe 10 elementi alla volta ... se dici 15 elementi, otterrai 1-10, l'11-15 come desideri.


9
Nota che anche YOUR_ARRAY verrà consumato (gli array sono oggetti ...)
Claudio

Sì, lo stavo solo mettendo perché a non è descrittivo, e ho già scritto l'esempio usando a ... è una riga di codice completamente inutile ... Anche se, questo mi fa pensare ... se si utilizza questo modello, potresti voler fare una copia completa in un array funzionante per non interrompere l'originale
jyore

@junvar IDK se quella riga 1 ha funzionato nel 2018 (dubito seriamente che lo abbia fatto), ma oggi fallisce miseramente. Non dovresti mai mutare (cioè rimuovere elementi) un array su cui si sta iterando, getta via l'indice, cioè dopo ogni rimozione dovrebbe essere riadattato dal numero di elementi rimossi, quindi "salta avanti" e non consuma il array interamente. Provalo
Drew Reese

107
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 differenza splice(), slice()non è distruttivo per l'array originale.


1
questa soluzione è migliore
Maduekwe Pedro

38

Basta scorrere l'array, unendolo fino a quando non è tutto consumato.



var a = ['a','b','c','d','e','f','g']
  , chunk

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

produzione


[ 'a', 'b', 'c' ]
[ 'd', 'e', 'f' ]
[ 'g' ]



13

Supponendo che tu non voglia distruggere l'array originale, puoi usare codice come questo per suddividere l'array lungo in array più piccoli su cui puoi quindi iterare:

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
}

6

Un'altra implementazione:

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 - Questo non modifica l'array originale.

Oppure, se preferisci un metodo funzionale, immutabile al 100% (anche se non c'è davvero niente di male nel mutare sul posto come fatto sopra) e autonomo:

function splitBy(size, list) {
  return list.reduce((acc, curr, i, self) => {
    if ( !(i % size)  ) {  
      return [
          ...acc,
          self.slice(i, i + size),
        ];
    }
    return acc;
  }, []);
}

5

Come supplemento alla risposta di @ jyore e nel caso in cui desideri comunque mantenere l'array originale:

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

5

Array.reduce potrebbe essere inefficiente per array di grandi dimensioni, specialmente con l'operatore mod. Penso che una soluzione funzionale più pulita (e forse più facile da leggere) sarebbe questa:

const chunkArray = (arr, size) =>
  arr.length > size
    ? [arr.slice(0, size), ...chunkArray(arr.slice(size), size)]
    : [arr];

3

Un altro metodo:

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

Ciò non influisce sull'array originale poiché una copia, creata utilizzando slice, viene passata nell'argomento "this" di map.


3

Vorrei condividere anche la mia soluzione. È un po 'più prolisso ma funziona anche.

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

Output (formattato):

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

2

Un'altra implementazione, usando Array.reduce (penso che sia l'unica mancante!):

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

Come molte soluzioni sopra, questa non è distruttiva. Restituire un array vuoto quando la dimensione è 0 è solo una convenzione. Se il ifblocco viene omesso, viene visualizzato un errore, che potrebbe essere quello che desideri.


1

Puoi dare un'occhiata a questo codice. Semplice ed efficace.

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

1

Ecco un semplice rivestimento

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


1

Più compatto:

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


0

Se vuoi un metodo che non modifichi l'array esistente, prova questo:

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

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

non dimenticare di creare: newArr = [] una variabile locale
zgthompson

Le risposte solo codice tendono a essere contrassegnate e quindi eliminate in quanto di bassa qualità. Potresti fornire qualche commento su come questo risolve il problema originale?
Graham

questo non funziona se la dimensione del blocco è inferiore alla dimensione dell'array di input.
r3wt

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

2
Benvenuto in stackoverflow. La tua risposta sarebbe migliorata aggiungendo qualche spiegazione.
Simon.SA

0

come una funzione

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

usare

arrayChunk(originalArray, 10) //10 being the chunk size.

0

usando la ricorsione

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: l'array esistente, ad esempio myArr, verrà modificato.


0

usando prototype possiamo impostare direttamente la classe array

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


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

uscita per la gamma 3

splittedArray === [[1,2,3][4,5,6][7,8,9][10,11]]

uscita per gamma 4

splittedArray === [[1,2,3,4][5,6,7,8][9,10,11]]

Potresti aggiungere una descrizione?
ego
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.