Teilen Sie das JavaScript-Array mit Lodash in Blöcke auf


82

Ich muss ein JavaScript-Array in ngroße Blöcke aufteilen .

Beispiel: Angesichts dieses Arrays

["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]

und a ngleich 4 sollte die Ausgabe folgende sein:

[ ["a1", "a2", "a3", "a4"],
  ["a5", "a6", "a7", "a8"],
  ["a9", "a10", "a11", "a12"],
  ["a13"]
]

Ich kenne reine JavaScript- Lösungen für dieses Problem, aber da ich bereits Lodash verwende, frage ich mich, ob Lodash eine bessere Lösung dafür bietet.

Bearbeiten:

Ich habe einen jsPerf-Test erstellt , um zu überprüfen, wie viel langsamer die Unterstrichlösung ist.

Antworten:


123

Schauen Sie sich lodash ' chunk an : https://lodash.com/docs#chunk

const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
const chunks = _.chunk(data, 3);
console.log(chunks);
// [
//  ["a1", "a2", "a3"],
//  ["a4", "a5", "a6"],
//  ["a7", "a8", "a9"],
//  ["a10", "a11", "a12"],
//  ["a13"]
// ]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


Es wäre hilfreich, wenn lodash und unterstreichen beide abwärtskompatiblen APIs
Jonno_FTW

@ Jonah Das stimmt. Die vorherige Antwort ist nicht mehr die beste, daher habe ich die akzeptierte Antwort zum Wohle der Leser aktualisiert :)
Cesar Canassa

90

Versuchen Sie für eine auf Unterstrichen basierende Lösung Folgendes:

var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.groupBy(data, function(element, index){
  return Math.floor(index/n);
});
lists = _.toArray(lists); //Added this to convert the returned object to an array.
console.log(lists);

Mit der Chain-Wrapper-Methode können Sie die beiden Anweisungen wie folgt kombinieren:

var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
var n = 3;
var lists = _.chain(data).groupBy(function(element, index){
  return Math.floor(index/n);
}).toArray()
.value();

1
Seltsamerweise gibt Underscore groupBy ein Objekt zurück , kein Array. Kein Dealbreaker - Sie erhalten im Grunde die gleiche Funktionalität - aber ein seltsames Stück Semantik. Edit: Oh, das macht es, um die Verkettbarkeit aufrechtzuerhalten. Immer noch interessant.
Jordan läuft

@Cesar Canassa: Für zukünftige Entwickler, die diesen Code lesen, sollten Sie ihn als Funktion in eine benutzerdefinierte Bibliothek aufnehmen, wenn Sie ihn häufig verwenden, oder ihn gut kommentieren, wenn Sie ihn nicht verwenden :)
Briguy37

@ Jordan: Hab das nicht gemerkt. Die Antwort wurde bearbeitet, um das Objekt in ein Array zu konvertieren.
Chandu

Ich bin zwar alle dafür, Underscore für die Dinge zu verwenden, die es am besten kann (und das OP hat nach einer Underscore-basierten Lösung gefragt, damit das nicht unverdient ist) und für funktionale Lösungen, aber es scheint, als würde diese Lösung eine Menge Overhead verursachen. Wie @ ajax33321 hervorhebt, ist spliceeine Schleife immer noch ein Dreiliner und, wie ich vermute, viel performanter. Wenn Ihre Arrays kurz sind, spielt es wahrscheinlich keine Rolle, aber wenn Sie mit Hunderten oder Tausenden von Elementen arbeiten, behalten Sie die Leistung im Auge.
Jordan läuft

1
Dies ist nicht mehr die beste Lösung. Bitte verwenden Sie stattdessen chunk ()
Jonah

4

Ein möglicherweise einfacherer Ausdruck:

const coll = [ "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9" ];
const n = 2;
const chunks = _.range(coll.length / n).map(i => coll.slice(i * n, (i + 1) * n));
console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>


1
Einfacher als was? Die Antworten sollten für sich allein stehen.
Nathan Tuggy

4

Unterstrich unterstützt _.chunk () nativ ab Version 1.9.0.

const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"];
const chunks = _.chunk(data, 4);
console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>


1

Probieren Sie dieses aus, es ist viel praktischer (wenn Sie beispielsweise das Array basierend auf der Anzahl der Elemente aufteilen möchten, die in jedem Unterarray als Container enthalten sein sollen):

function chunk(arr, start, amount){
    var result = [], 
        i, 
        start = start || 0, 
        amount = amount || 500, 
        len = arr.length;

    do {
        //console.log('appending ', start, '-', start + amount, 'of ', len, '.');
        result.push(arr.slice(start, start+amount));
        start += amount;

    } while (start< len);

    return result;
};

und die Verwendung in Ihrem Fall:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
    chunked = chunk(arr, 0, Math.floor(arr.length/3)); //to get 4 nested arrays

console.log(chunked);

und ein anderer Fall:

var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],
    chunked = chunk(arr, 0, 3); // to get 6 nested arrays each containing maximum of 3 items

console.log(chunked);

Dieser startParameter ist imho nicht wirklich praktisch. Normalerweise möchten Sie es nicht bestehen. Sie müssen jedoch immer die Blockgröße angeben. Tauschen Sie diese beiden Parameter besser aus.
Bergi

Warum ist das eine do whileSchleife? Niemand will leere Stücke bekommen.
Bergi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.