webentwicklung-frage-antwort-db.com.de

Array in Stücke aufteilen

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

356
Industrial

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
}
480
Blazemonger

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

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

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
}, [])
51
Andrei R

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

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;
};
24
Arek Flinik

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

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

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!

22

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

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

9
thoredge

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:

  1. Erstellen Sie einen neuen Chunk, wenn der vorherige Wert, d. H. Das zuvor zurückgegebene Array von Chunks, leer ist oder wenn der letzte vorherige Chunk chunkSize-Elemente enthält
  2. Fügen Sie den neuen Block dem Array der vorhandenen Blöcke hinzu
  3. Ansonsten ist der aktuelle Chunk der letzte Chunk im Array
  4. Fügen Sie den aktuellen Wert zum Block hinzu
  5. Gibt das modifizierte Array von Stücken zurück
  6. Initialisieren Sie die Reduktion, indem Sie ein leeres Array übergeben

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

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]]
7
Steve Holgado
results = []
chunk_size = 10
while(array.length > 0){
   results.Push(array.splice(0, chunk_size))
}
6
Jon

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;
6
zhiyelee

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

6

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

5
Redu

ES6-Einlinien-Ansatz basierend auf Array.prototypereduce 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]]
4
dhilt

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

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/

2
Suhair Zain

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

Generatoren verwenden

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

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.

2
dentaku

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

1
goofballLogic

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

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
1
pymarco

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);
1
Mohan Dere

Hier ist eine rekursive Lösung, die Tail-Call-Optimierung ist.

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

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

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

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

1
Chris Martin

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.

1
AGE

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

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

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:

Fiddle Beispiel

0
juan garcia

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


Erläuterung

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.

0
Chris

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. :)

0
Daniel Barde

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

})

0
Damian Green

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

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

0
Harunur Rashid

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

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