1046 Stimmen

Array in Stücke aufteilen

Nehmen wir an, dass ich ein Javascript-Array habe, 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 mit, sagen wir, höchstens 10 Elementen aufzuteilen?

32voto

Matias Kinnunen Punkte 6740

Eine weitere Lösung mit Array.prototype.reduce() :

const chunk = (array, size) =>
  array.reduce((acc, _, i) => {
    if (i % size === 0) acc.push(array.slice(i, i + size))
    return acc
  }, [])

// Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunked = chunk(numbers, 3)
console.log(chunked)

Diese Lösung ähnelt sehr der Lösung von Steve Holgado . Da diese Lösung jedoch keine Array-Spreizung verwendet und keine neuen Arrays in der Reduzierfunktion erstellt, ist sie schneller (siehe jsPerf-Test ) und subjektiv besser lesbar (einfachere Syntax) als die andere Lösung.

Bei jeder n-te Iteration (wobei n \= size ; beginnend mit der ersten Iteration), das Akkumulator-Array ( acc ) wird mit einem Stück des Arrays angehängt ( array.slice(i, i + size) ) und kehrte dann zurück. Bei anderen Iterationen wird das Akkumulator-Array so zurückgegeben, wie es ist.

Si size Null ist, gibt die Methode ein leeres Array zurück. Wenn size negativ ist, liefert die Methode fehlerhafte Ergebnisse. Falls in Ihrem Fall erforderlich, sollten Sie also etwas gegen negative oder nicht positive Ergebnisse unternehmen size Werte.


Wenn Geschwindigkeit in Ihrem Fall wichtig ist, kann eine einfache for Schleife wäre schneller als die Verwendung von reduce() (siehe die jsPerf-Test ), und manche finden diesen Stil vielleicht auch besser lesbar:

function chunk(array, size) {
  // This prevents infinite loops
  if (size < 1) throw new Error('Size must be positive')

  const result = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

28voto

Steve Holgado Punkte 10920

Es gibt viele Antworten, aber ich verwende diese:

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, ob bei der Division des Index durch die Chunk-Größe ein Rest übrig bleibt.

Wenn es einen Rest gibt, wird einfach das Akkumulator-Array zurückgegeben.

Wenn es keinen Rest gibt, dann ist der Index durch die Stückgröße teilbar, also nehmen Sie ein Stück aus dem ursprünglichen Array (beginnend mit dem aktuellen Index) und fügen Sie es dem Akkumulator-Array hinzu.

Das zurückgegebene Akkumulator-Array für jede Iteration von reduce sieht also etwa so aus:

// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

25voto

Ich denke, dies ist eine schöne rekursive Lösung mit ES6-Syntax:

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

24voto

nkitku Punkte 3128

ONE-LINER

const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));

Für TypeScript

const chunk = <T>(arr: T[], size: number): T[][] =>
  [...Array(Math.ceil(arr.length / size))].map((_, i) =>
    arr.slice(size * i, size + size * i)
  );

DEMO

const chunk = (a,n)=>[...Array(Math.ceil(a.length/n))].map((_,i)=>a.slice(n*i,n+n*i));
document.write(JSON.stringify(chunk([1, 2, 3, 4], 2)));

Chunk nach Anzahl der Gruppen

const part=(a,n)=>[...Array(n)].map((_,i)=>a.slice(i*Math.ceil(a.length/n),(i+1)*Math.ceil(a.length/n)));

Für TypeScript

const part = <T>(a: T[], n: number): T[][] => {
  const b = Math.ceil(a.length / n);
  return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};

DEMO

const part = (a, n) => {
    const b = Math.ceil(a.length / n);
    return [...Array(n)].map((_, i) => a.slice(i * b, (i + 1) * b));
};

document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6], 2))+'<br/>');
document.write(JSON.stringify(part([1, 2, 3, 4, 5, 6, 7], 2)));

19voto

user239558 Punkte 6552

Ok, fangen wir mit einer ziemlich knappen Sache 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); });
}

Das wird folgendermaßen verwendet:

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

Dann haben wir diese enge Reduzierfunktion:

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

Das wird folgendermaßen verwendet:

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

Da ein Kätzchen stirbt, wenn wir es binden this in eine Zahl umzuwandeln, können wir stattdessen manuell wie folgt vorgehen:

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

Das wird folgendermaßen verwendet:

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

Dann die immer noch recht knappe Funktion, die alles in einem Rutsch 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);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X