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?
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
}
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));
}});
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;
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
}, [])
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;
}
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;
};
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))
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]]
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!
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);
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 :-)
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:
chunkSize
.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' ] ]
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 ] ]
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]]
results = []
chunk_size = 10
while(array.length > 0){
results.Push(array.splice(0, chunk_size))
}
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;
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));
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));
Approche ES6 sur une ligne basée sur les méthodes Array.prototype
reduce
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]]
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;
}
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/
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);
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]]
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.
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;
}
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]) );
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)
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
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);
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]))
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);
}
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)
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));
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.
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]
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; }
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:
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]]
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 [[]]
.
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. :)
Pour une solution fonctionnelle, utilisez Ramda :
Où 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
})
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;
}
# 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 ' '
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);
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]]
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))
})