Nehmen wir an, ich habe ein Javascript-Array, das wie folgt aussieht:
["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.
Welcher Ansatz wäre angemessen, um das Array in viele kleinere Arrays zu unterteilen (sagen wir, höchstens 10 Elemente)?
Die Methode array.slice kann ein Slice vom Anfang, der Mitte oder vom Ende eines Arrays für beliebige Zwecke extrahieren, ohne das ursprüngliche Array zu ändern.
var i,j,temparray,chunk = 10;
for (i=0,j=array.length; i<j; i+=chunk) {
temparray = array.slice(i,i+chunk);
// do whatever
}
Geändert aus einer Antwort von 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)];
})
);
}
});
Demo:
> [1,2,3,4,5,6,7].chunk_inefficient(3)
[[1,2,3],[4,5,6],[7]]
kleiner Nachtrag:
Ich sollte darauf hinweisen, dass das obige eine nicht so elegante (in meinen Augen) elegante Lösung ist, um Array.map
zu verwenden. Es macht im Grunde Folgendes, wobei ~ Verkettung ist:
[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]
Es hat die gleiche asymptotische Laufzeit wie die unten beschriebene Methode, aber möglicherweise einen schlechteren konstanten Faktor, weil leere Listen erstellt werden. Man könnte dies wie folgt umschreiben (meistens das gleiche wie Blazemongers Methode, weshalb ich diese Antwort ursprünglich nicht eingereicht habe):
Effizientere Methode:
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
Mein bevorzugter Weg ist heutzutage der obige oder einer der folgenden:
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));
}
});
Demo:
> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]
Wenn Sie keine Array.range-Funktion wünschen, handelt es sich eigentlich nur um einen Einzeiler (außer Flusen):
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));
}});
oder
Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});
Versuchen Sie zu vermeiden, sich mit nativen Prototypen, einschließlich Array.prototype, zu beschäftigen, wenn Sie nicht wissen, wer Ihren Code verwenden wird (Drittanbieter, Kollegen, sich selbst zu einem späteren Zeitpunkt usw.).
Es gibt Möglichkeiten, Prototypen sicher zu erweitern (aber nicht in allen Browsern), und es gibt Wege, Objekte, die aus erweiterten Prototypen erstellt wurden, sicher zu konsumieren. Eine bessere Faustregel besteht jedoch darin, das Principle of Least Surprise zu beachten und diese Praktiken vollständig zu vermeiden .
Wenn Sie etwas Zeit haben, schauen Sie sich den JSConf 2011-Vortrag von Andrew Dupont an, "Alles ist erlaubt: Einbauten erweitern" , um eine gute Diskussion zu diesem Thema zu erhalten.
Aber zurück zu der Frage, obgleich die obigen Lösungen funktionieren werden, sind sie zu komplex und erfordern einen unnötigen Rechenaufwand. Hier ist meine Lösung:
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;
Hier ist eine ES6-Version, die die Verwendung von "verkleinern" verwendet
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']]
Und Sie sind bereit, weitere Zuordnungen zu verketten/zu reduzieren. Ihr Eingabearray bleibt erhalten
Wenn Sie eine kürzere, aber weniger lesbare Version bevorzugen, können Sie für das gleiche Endergebnis etwas concat
in den Mix einstreuen:
inputArray.reduce((all,one,i) => {
const ch = Math.floor(i/perChunk);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])
Ich habe die verschiedenen Antworten in jsperf.com getestet. Das Ergebnis ist dort verfügbar: http://jsperf.com/chunk-mtds
Und die schnellste Funktion (und das funktioniert ab IE8) ist diese:
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;
}
Ich würde lieber die Spleiß Methode verwenden:
var chunks = function(array, size) {
var results = [];
while (array.length) {
results.Push(array.splice(0, size));
}
return results;
};
Einliner in 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))
Alte Frage: Neue Antwort! Ich arbeitete gerade mit einer Antwort aus dieser Frage und hatte einen Freund, der sie verbessern konnte! Hier ist es also:
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]]
Heutzutage können Sie die lodash'-Chunk-Funktion verwenden, um das Array in kleinere Arrays aufzuteilen https://lodash.com/docs#chunk Sie müssen nicht mehr mit den Loops herumspielen!
Ok, fangen wir mit einem ziemlich engen an:
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); });
}
Welches wird wie folgt verwendet:
chunk([1,2,3,4,5,6,7], 2);
Dann haben wir diese enge Reduktionsfunktion:
function chunker(p, c, i) {
(p[i/this|0] = p[i/this|0] || []).Push(c);
return p;
}
Welches wird wie folgt verwendet:
[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);
Da ein Kätzchen stirbt, wenn wir this
an eine Zahl binden, können Sie stattdessen manuelles Currying durchführen:
// 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;
};
}
Welches wird wie folgt verwendet:
[1,2,3,4,5,6,7].reduce(chunker(3),[]);
Dann die noch recht enge Funktion, die alles auf einmal erledigt:
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);
Ich zielte darauf ab, eine einfache, nicht mutierende Lösung in ES6 zu schaffen. Besonderheiten in Javascript machen es notwendig, das leere Array vor dem Mapping zu füllen :-(
function chunk(a, l) {
return new Array(Math.ceil(a.length / l)).fill(0)
.map((_, n) => a.slice(n*l, n*l + l));
}
Diese Version mit Rekursion erscheint einfacher und überzeugender:
function chunk(a, l) {
if (a.length == 0) return [];
else return [a.slice(0, l)].concat(chunk(a.slice(l), l));
}
Die lächerlich schwachen Array-Funktionen von ES6 sorgen für gute Rätsel :-)
Wenn Sie die EcmaScript-Version> = 5.1 verwenden, können Sie eine funktionale Version von chunk()
mithilfe von array.reduce () implementieren, das die Komplexität O(N) aufweist:
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' ] ]
Erklärung zu jedem // nbr
oben:
chunkSize
-Elemente enthältCurrying basierend auf chunkSize
:
var chunk3 = function(array) {
return chunk(3, array);
};
console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]
Sie können die chunk()
-Funktion zum globalen Array
-Objekt hinzufügen:
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 ] ]
Es gab viele Antworten, aber das verwende ich:
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]]
Prüfen Sie zunächst nach einem Rest, wenn Sie den Index durch die Blockgröße teilen.
Wenn ein Rest vorhanden ist, geben Sie einfach das Akkumulator-Array zurück.
Wenn kein Rest vorhanden ist, ist der Index durch die Blockgröße teilbar. Nehmen Sie daher ein Stück vom ursprünglichen Array (beginnend am aktuellen Index) und fügen Sie es dem Akkumulatorarray hinzu.
Das zurückgegebene Akkumulator-Array für jede Iteration von "verkleinern" sieht in etwa so aus:
// 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))
}
Erstellt ein npm-Paket für dieses 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;
Ich denke, dass dies eine schöne rekursive Lösung mit ES6-Syntax ist:
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));
Und das wäre mein Beitrag zu diesem Thema. Ich denke, .reduce()
ist der beste Weg.
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));
Die obige Implementierung ist jedoch nicht sehr effizient, da .reduce()
alle arr
-Funktionen durchläuft. Ein effizienterer Ansatz (sehr nahe an der schnellsten imperativen Lösung) wäre das Iterieren über das reduzierte (zu chunkende) Array, da wir seine Größe im Voraus mit Math.ceil(arr/n);
berechnen können. Sobald wir das leere Ergebnis-Array wie Array(Math.ceil(arr.length/n)).fill();
haben, besteht der Rest darin, Slices des arr
-Arrays darin zuzuordnen.
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));
ES6-Einlinien-Ansatz basierend auf Array.prototype
reduce
und 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]]
Dies ist die effizienteste und einfachste Lösung, die mir einfällt:
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;
}
Hier ist eine nicht mutierende Lösung, die nur Rekursion und Slice () verwendet.
const splitToChunks = (arr, chunkSize, acc = []) => (
arr.length > chunkSize ?
splitToChunks(
arr.slice(chunkSize),
chunkSize,
[...acc, arr.slice(0, chunkSize)]
) :
[...acc, arr]
);
Dann verwenden Sie es einfach wie splitToChunks([1, 2, 3, 4, 5], 3)
, um [[1, 2, 3], [4, 5]]
zu erhalten.
Hier ist eine Geige zum Ausprobieren: https://jsfiddle.net/6wtrbx6k/2/
ES6 Generator 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]]
BEARBEITEN: @ mblase75 fügte der früheren Antwort noch präziseren Code hinzu, als ich meine schrieb, daher empfehle ich, mit seiner Lösung zu arbeiten.
Sie könnten Code wie folgt verwenden:
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));
}
Ändern Sie den Wert von arraySize
, um die maximale Länge der kleineren Arrays zu ändern.
Dies sollte eine einfache Antwort ohne viele mathematische Komplikationen sein.
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 verbreitet funktionelle #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]) );
Hi versuch das -
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)
Hier ist mein Ansatz mit dem Verständnis der Coffeescript-Liste. Ein großartiger Artikel, der Details zu Coffeescript beschreibt, ist hier zu finden .
chunk: (arr, size) ->
chunks = (arr.slice(index, index+size) for item, index in arr by size)
return chunks
Hier ist eine übersichtliche und optimierte Implementierung der Funktion chunk()
. Angenommen, die standardmäßige Chunkgröße ist 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]))
Ich habe BlazeMonger's leicht geändert, um für ein jQuery-Objekt verwendet zu werden.
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);
}
Der folgende ES2015-Ansatz funktioniert, ohne eine Funktion und direkt auf anonyme Arrays definieren zu müssen (Beispiel mit Blockgröße 2):
[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)
Wenn Sie dafür eine Funktion definieren möchten, können Sie dies folgendermaßen tun (Verbesserung von K ._s Kommentar zu Blazemongers Antwort ):
const array_chunks = (array, chunk_size) => array
.map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
.filter(x => x.length)
Ich habe dies gerade mit Hilfe einer groupBy-Funktion geschrieben.
// 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));
Ich habe das folgende JSFiddle erstellt, um meine Herangehensweise an Ihre Frage zu demonstrieren.
(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;
}
}
Ich habe zunächst zwei Beispiele: ein Array mit weniger als acht Elementen, ein anderes mit einem Array mit mehr als acht Elementen (kommentieren Sie das, was Sie nicht verwenden möchten).
Ich überprüfe dann die Größe des Arrays, einfach, aber um zusätzliche Berechnungen zu vermeiden. Wenn das Array die Kriterien (Arraygröße> delimiter
) erfüllt, wechseln wir von hier aus in die Funktion splitArray
.
Die splitArray
-Funktion enthält das Trennzeichen (dh 8, da dies das ist, was Sie teilen möchten) und das Array selbst. Da wir die Arraylänge häufig wiederverwenden, cache ich sie in einer Variablen sowie in first
und last
.
first
repräsentiert die Position des ersten Elements in einem Array. Dieses Array ist ein Array aus 8 Elementen. Um das erste Element zu bestimmen, verwenden wir den modulus-Operator.
myArrays
ist das Array von Arrays. Darin speichern wir an jedem Index jedes Unterfeld der Größe 8 oder darunter. Dies ist die Schlüsselstrategie im nachstehenden Algorithmus.
index
repräsentiert den Index für die Variable myArrays
. Jedes Mal, wenn ein Sub-Array mit 8 oder weniger Elementen gespeichert werden soll, muss es im entsprechenden Index gespeichert werden. Wenn wir also 27 Elemente haben, bedeutet das 4 Arrays. Das erste, zweite und dritte Array hat jeweils 8 Elemente. Das letzte hat nur 3 Elemente. index
ist also 0, 1, 2 und 3.
Der schwierige Teil berechnet einfach die Mathematik und optimiert sie so gut wie möglich. Zum Beispiel else if (delimiter - (i % delimiter) === 1)
suchen Sie das letzte Element, das in das Array gehen soll, wenn ein Array voll ist (Beispiel: 10 Elemente enthalten).
Dieser Code funktioniert für jedes einzelne Szenario. Sie können sogar die Variable delimiter
ändern, um sie an die gewünschte Array-Größe anzupassen. Ziemlich süß richtig :-)
Irgendwelche Fragen? Fühlen Sie sich frei, in den Kommentaren unten zu fragen.
Ich bevorzuge die Verwendung der Splice-Methode anstelle von Slice .. Diese Lösung verwendet die Arraylänge und die Blockgröße, um eine Schleifenanzahl zu erstellen, und schleift dann über das Array, das nach jeder Operation aufgrund des Splicings in jedem Schritt kleiner wird.
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);
Wenn Sie das ursprüngliche Array nicht mutieren möchten, können Sie das ursprüngliche Array mit dem Spread-Operator klonen und dann dieses Array verwenden, um das Problem zu lösen.
let clonedArray = [...OriginalArray]
Ich habe folgendes für den gleichen Zweck verwendet, der für mich perfekt funktionierte. hoffe das hilft jemandem
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; }
Noch eine Lösung XD, mit reinem 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);
Und hier ist eine elegantere Lösung, mit einer Stufe mit der gleichen Größe der aufgeteilten Gruppen:
// 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);
}
Sie können eine Funktion für die Wiederverwendbarkeit verwenden. Die Ergebnisse für die Aufteilung in 3 sind:
[[1, 2, 3], [4, 5, 6], [7, 8]]
Für die Zweiteilung sind:
[[1, 2], [3, 4], [5, 6], [7, 8]]
Der ursprüngliche Zahlensatz wird nicht beschädigt.
Hier ist die Geige:
Hier ist eine andere Lösung mit der Methode verkleinern () , die sich jedoch leicht von anderen Beispielen unterscheidet. Hoffentlich ist meine Erklärung auch etwas klarer.
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]]
Wir rufen einen Reduzierer an, der für jedes Element im Array das letzte Element des Akkus mit pop()
abruft. Denken Sie daran, dass dieses Element ein Array ist, das bis zu chunkSize
Anzahl der Elemente gruppiert (in diesem Beispiel 3).
Wenn und nur wenn diese Gruppe eine Arraylänge hat, die chunksize
entspricht, müssen wir die Gruppe wieder in den Akkumulator einfügen und eine neue Gruppe erstellen.
Wir schieben dann das aktuelle item
in unser group
-Array (das bereits 0, 1 oder 2 Elemente aus den vorherigen Schritten enthalten kann). Wenn das aktuelle item
in group
eingefügt ist, müssen wir das group
wieder in die größere Sammlung einfügen.
Der Vorgang wird wiederholt, bis wir alle Elemente in arr
durchlaufen haben.
Beachten Sie, dass wir dem Reduzierer auch den Startwert eines leeren Arrays innerhalb eines Arrays mit [[]]
zur Verfügung gestellt haben.
Ihr ist eine einfache Lösung, die @ Blazemonger-Lösung verwendet
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
}
Das hat die Pipeline für mich zum Fließen gebracht, ich hoffe, das hilft jemandem da draußen. :)
Für eine funktionale Lösung verwenden Sie Ramda :
Wo popularProducts
Ihr Eingabearray ist, ist 5
die Blockgröße
import splitEvery from 'ramda/src/splitEvery'
splitEvery(5, popularProducts).map((chunk, i) => {
// do something with chunk
})
mein Trick besteht darin, parseInt(i/chunkSize)
und parseInt(i%chunkSize)
zu verwenden und dann das Array zu füllen
// 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 ' '
Versuche dies :
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);
Hier ist eine Version mit Tail-Rekursion und Array-Zerstörung.
Weit weg von der schnellsten Leistung , aber ich bin nur amüsiert, dass js das jetzt kann. Auch wenn es nicht dafür optimiert ist :(
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]]
Hier ist eine Lösung, die ImmutableJS verwendet, wobei items
eine unveränderliche Liste und size
die erforderliche Gruppierungsgröße ist.
const partition = ((items, size) => {
return items.groupBy((items, i) => Math.floor(i/size))
})