web-dev-qa-db-fra.com

Diviser un tableau en morceaux

Disons que j'ai un tableau Javascript ressemblant à ceci: 

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

Quelle approche conviendrait pour diviser le tableau en plusieurs tableaux plus petits, avec, disons, 10 éléments au maximum?

356
Industrial

La méthode array.slice peut extraire une tranche du début, du milieu ou de la fin d'un tableau à toutes les fins requises, sans modifier le tableau d'origine.

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

Modifié à partir d'une réponse de 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)];
            })
        );
    }
});

Démo:

> [1,2,3,4,5,6,7].chunk_inefficient(3)
[[1,2,3],[4,5,6],[7]]

addenda mineur:

Je tiens à souligner que la solution ci-dessus est une solution de contournement pas très élégante (dans mon esprit) consistant à utiliser Array.map. Il fait essentiellement ce qui suit, où ~ est une concaténation:

[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]

Il a la même durée de fonctionnement asymptotique que la méthode ci-dessous, mais peut-être un facteur constant pire en raison de la construction de listes vides. On pourrait réécrire ceci comme suit (essentiellement la même chose que la méthode de Blazemonger, c'est pourquoi je n'ai pas soumis cette réponse à l'origine):

Méthode plus efficace:

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

Ma façon préférée de nos jours est la suivante, ou l’une des suivantes:

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

  }
});

Démo:

> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]

Ou si vous ne voulez pas d'une fonction Array.range, c'est en fait un one-liner (sans les peluches):

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

ou

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

Si vous ne savez pas qui consommera votre code (tiers, collègues, vous-même, etc.), évitez de vous mêler aux prototypes natifs, y compris Array.prototype.

Il existe des moyens d'étendre en toute sécurité les prototypes (mais pas dans tous les navigateurs) et de consommer en toute sécurité des objets créés à partir de prototypes étendus, mais une meilleure règle empirique consiste à suivre le principe de la moindre surprise et à les éviter. pratiques tout à fait.

Si vous avez un peu de temps, regardez la conférence JSConf 2011 d'Andrew Dupont, "Tout est permis: extension des programmes intégrés" , pour une bonne discussion sur ce sujet. 

Mais revenons à la question, bien que les solutions ci-dessus fonctionnent, elles sont trop complexes et nécessitent un temps de calcul inutile. Voici ma solution:

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;
76
furf

Voici une version ES6 en utilisant réduire

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

Et vous êtes prêt à enchaîner davantage de transformations de mappe/réduction . Votre tableau d’entrée est laissé intact


Si vous préférez une version plus courte mais moins lisible, vous pouvez saupoudrer un concat dans le mixage pour le même résultat final:

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

J'ai testé les différentes réponses sur jsperf.com. Le résultat est disponible ici: http://jsperf.com/chunk-mtds

Et la fonction la plus rapide (et qui fonctionne à partir d’IE8) est celle-ci:

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

Je préférerais utiliser splice method:

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

One-Liner dans 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))
23
Shairon Toledo

Ancienne question: Nouvelle réponse! En fait, je travaillais avec une réponse à cette question et un ami l'a améliorée! Alors la voici: 

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

De nos jours, vous pouvez utiliser la fonction chod de lodash pour diviser le tableau en tableaux plus petits https://lodash.com/docs#chunk Plus besoin de jouer avec les boucles!

20
George Herolyants

Ok, commençons par un assez serré:

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

Qui est utilisé comme ceci:

chunk([1,2,3,4,5,6,7], 2);

Ensuite, nous avons cette fonction de réducteur serré:

function chunker(p, c, i) {
    (p[i/this|0] = p[i/this|0] || []).Push(c);
    return p;
}

Qui est utilisé comme ceci:

[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);

Étant donné qu'un chaton meurt lorsque nous lions this à un numéro, nous pouvons effectuer un curry manuel comme ceci:

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

Qui est utilisé comme ceci:

[1,2,3,4,5,6,7].reduce(chunker(3),[]);

Puis la fonction encore assez serrée qui fait tout en un:

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

Je souhaitais créer une solution simple et non mutante dans ES6 pur. Les particularités de javascript rendent nécessaire le remplissage du tableau vide avant le mapping :-(

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

Cette version avec récursion semble plus simple et plus convaincante:

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

Les fonctions de tableau ridiculement faibles de l'ES6 permettent de réaliser de bons casse-tête :-)

9
thoredge

Si vous utilisez EcmaScript version> = 5.1, vous pouvez implémenter une version fonctionnelle de chunk() en utilisant array.reduce () qui présente une complexité O(N):

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

Explication de chaque // nbr ci-dessus:

  1. Créez un nouveau bloc si la valeur précédente, c'est-à-dire le tableau de blocs renvoyé précédemment, est vide ou si le dernier bloc précédent contient des éléments chunkSize.
  2. Ajouter le nouveau bloc au tableau de morceaux existants
  3. Sinon, le morceau actuel est le dernier morceau du tableau de morceaux.
  4. Ajouter la valeur actuelle au morceau
  5. Retourne le tableau modifié de morceaux
  6. Initialiser la réduction en passant un tableau vide

Curry basé sur chunkSize:

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

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

Vous pouvez ajouter la fonction chunk() à l'objet global 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' ] ]
7
matsev
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 ] ]
7
Arpit Jain

Il y a eu beaucoup de réponses mais voici ce que j'utilise:

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

Commencez par rechercher un reste lors de la division de l'index par la taille du bloc.

S'il y a un reste, retournez simplement le tableau accumulateur.

S'il n'y a pas de reste, alors l'index est divisible par la taille du fragment, prenez donc une tranche du tableau d'origine (en commençant par l'index actuel) et ajoutez-la au tableau d'accumulation.

Ainsi, le tableau accumulateur retourné pour chaque itération de réduire ressemble à ceci:

// 0: [[1, 2, 3, 4]]
// 1: [[1, 2, 3, 4]]
// 2: [[1, 2, 3, 4]]
// 3: [[1, 2, 3, 4]]
// 4: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 5: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 6: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 7: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 8: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
// 9: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
7
Steve Holgado
results = []
chunk_size = 10
while(array.length > 0){
   results.Push(array.splice(0, chunk_size))
}
6
Jon

Création d'un package npm pour cette https://www.npmjs.com/package/array.chunk

  var result = [];
  for (var i = 0; i < arr.length; i += size) {
    result.Push(arr.slice(i, size + i));
  }

  return result;
6
zhiyelee

Je pense que c'est une solution récursive de Nice avec la syntaxe 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));

6

Et ce serait ma contribution à ce sujet. Je suppose que .reduce() est le meilleur moyen.

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

Mais l’implémentation ci-dessus n’est pas très efficace puisque .reduce() exécute toutes les fonctions arr. Une approche plus efficace (très proche de la solution impérative la plus rapide) consisterait à parcourir le tableau réduit (à découper) étant donné que nous pouvons calculer sa taille à l'avance par Math.ceil(arr/n);. Une fois que nous avons le tableau de résultats vide comme Array(Math.ceil(arr.length/n)).fill();, le reste consiste à mapper des tranches du tableau arr dans celui-ci.

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

5
Redu

Approche ES6 sur une ligne basée sur les méthodes Array.prototypereduce et Push:

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

C'est la solution la plus efficace et la plus simple à laquelle je puisse penser:

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

Voici une solution non mutante utilisant uniquement la récursivité et slice ().

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

Ensuite, utilisez-le simplement comme splitToChunks([1, 2, 3, 4, 5], 3) pour obtenir [[1, 2, 3], [4, 5]].

Voici un violon à essayer: https://jsfiddle.net/6wtrbx6k/2/

2
Suhair Zain

ES6 Générateur version

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

Utiliser des générateurs

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]]
2
Ikechukwu Eze

EDIT: @ mblase75 a ajouté un code plus concis à la réponse précédente pendant que j'écrivais la mienne. Je vous recommande donc de choisir sa solution.

Vous pouvez utiliser un code comme ceci:

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

Modifiez la valeur arraySize pour modifier la longueur maximale des tableaux plus petits.

2
dentaku

Cela devrait être une réponse simple sans beaucoup de complications mathématiques.

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

ES6 se répand fonctionnel #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]) );

1
goofballLogic

Salut essayez ceci -

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

Voici mon approche utilisant la compréhension de liste de Coffeescript. Un bon article détaillant les compréhensions dans Coffeescript peut être trouvé ici .

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

Voici une implémentation soignée et optimisée de la fonction chunk(). En supposant que la taille de bloc par défaut est 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);
1
Mohan Dere

Voici une solution récursive qui consiste à optimiser l'appel final.

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]))
1
Chris Vouga

J'ai légèrement modifié BlazeMonger pour l'utiliser pour un objet 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);
}
1
nevace

L'approche ES2015 suivante fonctionne sans avoir à définir de fonction et directement sur des tableaux anonymes (exemple avec la taille de bloc 2):

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

Si vous voulez définir une fonction pour cela, vous pouvez le faire comme suit (en améliorant le commentaire de K ._ sur La réponse de Blazemonger ):

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

Je viens d'écrire ceci avec l'aide d'une fonction 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));

1
Chris Martin

J'ai créé ce qui suit JSFiddle pour illustrer mon approche de votre question.

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

Tout d’abord, j’ai deux exemples: un tableau avec moins de huit éléments, un autre avec un tableau avec plus de huit éléments (commentez celui que vous ne voulez pas utiliser).

Je vérifie ensuite la taille du tableau, simple mais indispensable pour éviter des calculs supplémentaires. À partir de là, si le tableau répond aux critères (taille du tableau> delimiter), nous passons à la fonction splitArray.

La fonction splitArray prend le délimiteur (c'est-à-dire 8, puisque c'est ce que vous voulez diviser par) et le tableau lui-même. Puisque nous réutilisons beaucoup le tableau, je le cache dans une variable, ainsi que dans les variables first et last.

first représente la position du premier élément d'un tableau. Ce tableau est un tableau composé de 8 éléments. Donc, pour déterminer le premier élément, nous utilisons l'opérateur modulus.

myArrays est le tableau de tableaux. Nous y stockons, à chaque index, tout sous-tableau de taille inférieure ou égale à 8. C'est la stratégie clé de l'algorithme ci-dessous.

index représente l'index de la variable myArrays. Chaque fois qu'un sous-tableau de 8 éléments ou moins doit être stocké, il doit être stocké dans l'index correspondant. Donc, si nous avons 27 éléments, cela signifie 4 tableaux. Les premier, deuxième et troisième tableaux auront 8 éléments chacun. Le dernier aura 3 éléments seulement. Donc index sera 0, 1, 2 et 3 respectivement.

La partie la plus délicate} _ consiste simplement à calculer et à optimiser le calcul au mieux. Par exemple, else if (delimiter - (i % delimiter) === 1) ceci permet de trouver le dernier élément devant figurer dans le tableau, lorsqu'un tableau sera plein (exemple: contient 10 éléments).

Ce code fonctionne pour chaque scénario. Vous pouvez même modifier la variable delimiter pour qu'elle corresponde à la taille du tableau que vous souhaitez obtenir. Assez doux à droite :-)

Des questions? N'hésitez pas à demander dans les commentaires ci-dessous.

1
AGE

Je préfère utiliser la méthode de raccordement au lieu de slice . Cette solution utilise la longueur du tableau et la taille du segment pour créer un nombre de boucles, puis boucle sur le tableau qui devient plus petit après chaque opération en raison du raccordement de chaque étape.

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

Si vous ne souhaitez pas que le tableau d'origine soit modifié, vous pouvez cloner le tableau d'origine à l'aide de l'opérateur de propagation, puis utiliser ce tableau pour résoudre le problème.

    let clonedArray = [...OriginalArray]
0
SeaWarrior404

J'ai utilisé suivre pour le même but qui a parfaitement fonctionné pour moi. espérons que cela aide quelqu'un

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;
}
0
Jack Gajanan

Encore une autre solution XD, avec pure js.

let numbers = [1,2,3,4,5,6,7,8]; // Initial values

let groups = []; // The grouped values
let group = 0; // Group Index
let split = 3; // I will split in groups of 3 items

for(let i = 0, length = numbers.length; i < length; i++) {
    if (Math.floor(i / split) !== group) {
        //I need a new group in this case, so I make a new index
        group += 1;
    }
    if (!groups[group]) {
        //If I don't have the group of this index, create a new group array
        groups[group] = [];
    }
    //I add the numbers or letters to the group
    groups[group].Push(numbers[i]);
}
console.log(groups);

Et voici une solution plus élégante, avec un pour avec des étapes de la même taille que les groupes séparés:

// Another options more elegant:
let numbers = [1,2,3,4,5,6,7,8]; // Initial values
let groups2 = []; // The grouped values
let split = 3;
for(let i = 0, j = 0, length = numbers.length; i < length; i+=split, j++) {
    groups2[j] = numbers.slice(i, i + split);
}

Vous pouvez utiliser une fonction pour la réutilisabilité ... les résultats pour le fractionnement en 3 sont:

[[1, 2, 3], [4, 5, 6], [7, 8]]

Pour scinder en 2 sont:

[[1, 2], [3, 4], [5, 6], [7, 8]]

Cela ne casse pas la série initiale de nombres.

Voici le violon:

Fiddle exemple

0
juan garcia

Voici une autre solution avec la méthode reduction () , bien que légèrement différente des autres exemples. J'espère que mon explication est aussi un peu plus claire.

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


Explication

Nous appelons un réducteur qui, pour chaque élément du tableau, obtient le dernier élément de l'accumulateur avec pop(). N'oubliez pas que cet élément est un tableau qui regroupe jusqu'à chunkSize nombre d'éléments (3 dans cet exemple).

Si, et seulement si, ce groupe a une longueur de tableau égale à chunksize, nous devons réinsérer le groupe dans l'accumulateur et créer un nouveau groupe.

Nous poussons ensuite la item actuelle dans notre tableau group (qui peut déjà contenir 0, 1 ou 2 éléments des étapes précédentes). La item actuelle étant insérée dans la group, nous devons réinsérer la group dans la collection la plus grande.

Le processus sera répété jusqu'à ce que nous ayons parcouru tous les éléments de arr.

Notez que nous avons également fourni au réducteur la valeur de départ d'un tableau vide à l'intérieur d'un tableau avec [[]].

0
Chris

Her est une solution simple utilisant la solution @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
}

Cela m'a permis de faire couler l'oléoduc, espérons que cela aidera quelqu'un d'autre. :)

0
Daniel Barde

Pour une solution fonctionnelle, utilisez Ramda :

popularProducts est votre tableau d’entrée, 5 est la taille du bloc

import splitEvery from 'ramda/src/splitEvery'

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

})

0
Damian Green

mon astuce consiste à utiliser parseInt(i/chunkSize) et parseInt(i%chunkSize), puis à remplir le tableau

// 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;
 }
0
NuOne
# 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 ' '
0
Patrick Chu

Essaye ça : 

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

0
Harunur Rashid

Voici une version avec récursion de la queue et déstructuration du tableau. 

Loin de la performance la plus rapide , mais je suis juste amusé que js peut le faire maintenant. Même si ce n’est pas optimisé pour cela :(

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

Voici une solution utilisant ImmutableJS, où items est une liste immuable et size est la taille de groupe requise.

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