web-dev-qa-db-fra.com

Comment scinder un tableau long en tableaux plus petits, avec JavaScript

J'ai un tableau d'e-mails (il ne peut s'agir que d'un courrier électronique ou de 100 courriers électroniques), et je dois envoyer le tableau avec une demande ajax (que je sais comment faire), mais je ne peux envoyer qu'un tableau contenant 10 e-mails ou moins. Donc, s'il y a un tableau original de 20 courriels, je devrai les séparer en deux tableaux de 10 chacun. ou s'il y a 15 e-mails dans le tableau d'origine, puis 1 tableau de 10 et un autre tableau de 5. J'utilise jQuery, quel serait le meilleur moyen de le faire? 

60
Bill

N'utilisez pas jquery ... utilisez du javascript pur

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

Vous pouvez faire une boucle pour obtenir le comportement souhaité.

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

Cela vous donnerait 10 éléments à la fois ... si vous dites 15 éléments, vous obtiendrez 1-10, les 11-15 comme vous le souhaitez.

136
jyore
var size = 10; var arrayOfArrays = [];
for (var i=0; i<bigarray.length; i+=size) {
     arrayOfArrays.Push(bigarray.slice(i,i+size));
}
console.log(arrayOfArrays);

Contrairement à splice() , slice() est non destructif pour le tableau d'origine.

74
Blazemonger

Passez simplement en boucle sur le tableau, en l'épissant jusqu'à ce que tout soit consommé.



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

while (a.length > 0) {

  chunk = a.splice(0,3)

  console.log(chunk)

}

sortie


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

26
Claudio

Vous pouvez utiliser lodash: https://lodash.com/docs

_.chunk(['a', 'b', 'c', 'd'], 2);
// → [['a', 'b'], ['c', 'd']]
24
AlexParamonov

En supposant que vous ne voulez pas détruire le tableau d'origine, vous pouvez utiliser un code comme celui-ci pour diviser le tableau long en tableaux plus petits sur lesquels vous pouvez ensuite effectuer une itération:

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
}
9
jfriend00

En complément à @ - jyore answer , et si vous souhaitez toujours conserver le tableau d'origine: 

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
Justin

Une autre méthode:

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

Cela n'affecte pas le tableau d'origine car une copie, réalisée à l'aide de slice, est passée dans l'argument 'this' de map.

3
AFurlepa

J'aimerais aussi partager ma solution. C'est un peu plus verbeux mais ça marche aussi.

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

Sortie (formatée):

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

Une autre implémentation:

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 - Cela ne modifie pas le tableau d'origine.

Ou, si vous préférez une méthode fonctionnelle, immuable et autonome:

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

Voici un simple paquebot

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
Redu

Une autre implémentation, utilisant Array.reduce (je pense que c’est le seul qui manque!):

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

Comme beaucoup de solutions ci-dessus, celle-ci est non destructive. Renvoyer un tableau vide lorsque la taille est 0 n'est qu'une convention. Si le bloc if est omis, vous obtenez une erreur, ce qui pourrait être ce que vous voulez.

1
Alf

Vous pouvez jeter un oeil à ce code. Simple et 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
Subhankar

Si vous voulez une méthode qui ne modifie pas le tableau existant, essayez ceci:

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
Ryan

Plus compact:

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
dzuc
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);
0
Ridwanullah Ibrahim
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);
0
zgthompson

Array.reduce peut être inefficace pour les grands tableaux, en particulier avec l'opérateur mod. Je pense qu'une solution fonctionnelle plus propre (et peut-être plus facile à lire) serait la suivante:

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