Wie finde ich die Indizes aller Vorkommen eines Elements im Array?

Lesezeit: 6 Minuten

Benutzeravatar von norbdum
norddum

Ich versuche, die Indizes aller Instanzen eines Elements, sagen wir “Nano”, in einem JavaScript-Array zu finden.

var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];

Ich habe es versucht jQuery.inArrayoder ähnlich, .Index von()aber es gab nur den Index der letzten Instanz des Elements, dh in diesem Fall 5.

Wie bekomme ich es für alle Instanzen?

Benutzeravatar von nnnnnn
nnnnn

Die .indexOf() Methode hat einen optionalen zweiten Parameter, der den Index angibt, ab dem die Suche beginnen soll, sodass Sie ihn in einer Schleife aufrufen können, um alle Instanzen eines bestimmten Werts zu finden:

function getAllIndexes(arr, val) {
    var indexes = [], i = -1;
    while ((i = arr.indexOf(val, i+1)) != -1){
        indexes.push(i);
    }
    return indexes;
}

var indexes = getAllIndexes(Cars, "Nano");

Sie machen nicht wirklich klar, wie Sie die Indizes verwenden möchten, also gibt meine Funktion sie als Array zurück (oder gibt ein leeres Array zurück, wenn der Wert nicht gefunden wird), aber Sie könnten etwas anderes mit den einzelnen Indexwerten machen innerhalb der Schleife.

UPDATE: Laut dem Kommentar von VisioN würde eine einfache for-Schleife die gleiche Aufgabe effizienter erledigen, und sie ist einfacher zu verstehen und daher einfacher zu warten:

function getAllIndexes(arr, val) {
    var indexes = [], i;
    for(i = 0; i < arr.length; i++)
        if (arr[i] === val)
            indexes.push(i);
    return indexes;
}

  • Es scheint nicht die schnellere Alternative zu einer Single zu sein for Schleife mit Füllen des Index-Arrays.

    – Vision

    27. Dezember 2013 um 10:04 Uhr

  • @VisioN – Ja, eine einfache for-Schleife, die über das Array iteriert, wäre auch einfacher, aber da das OP erwähnt hat, versucht es zu verwenden .indexOf() Ich wollte zeigen, dass es funktionieren kann. (Ich denke, ich dachte, das OP könnte herausfinden, wie es mit einer for-Schleife geht.) Natürlich gibt es andere Möglichkeiten, dies zu tun, z. Cars.reduce(function(a, v, i) { if (v==="Nano") a.push(i); return a; }, []);

    – nnnnn

    27. Dezember 2013 um 10:07 Uhr


  • Ich kann sagen, dass du aus Nordamerika kommst, weil du benutzt hast indexes anstatt indices 😛

    – 4 Schloss

    14. April 2016 um 21:22 Uhr


  • @4castle – Ha. Nein, bin ich nicht. “Indizes” und “Indizes” sind beide richtig, und ich neige dazu, zwischen den beiden zu wechseln. Ich hatte das nie als regionales Dialekt-Ding betrachtet. Interessant.

    – nnnnn

    14. April 2016 um 22:31 Uhr


  • @IgorFomenko – Danke für den Vorschlag. Es ist nicht wirklich eine “Berechnung”, es ist nur eine Eigenschaftssuche, aber tatsächlich mache ich oft Codeschleifen gemäß Ihrem Vorschlag, aber ich mache es normalerweise nicht in StackOverflow-Antworten, wenn es nicht direkt relevant für die Frage ist. Wie sicher sind Sie, dass der JS-Compiler diese Optimierung nicht automatisch hinter den Kulissen durchführt?

    – nnnnn

    20. August 2020 um 9:43 Uhr


Eine andere alternative Lösung ist die Verwendung Array.prototype.reduce():

["Nano","Volvo","BMW","Nano","VW","Nano"].reduce(function(a, e, i) {
    if (e === 'Nano')
        a.push(i);
    return a;
}, []);   // [0, 3, 5]

Hinweis: Überprüf den Browser-Kompatibilität Pro reduce Methode und Verwendung Polyfill Falls erforderlich.

  • +1. Lustiger Zufall: Ich habe gerade meine Antwort auf Ihren Kommentar unter meiner Antwort bearbeitet, um genau diese Lösung vorzuschlagen, dann aktualisiere ich und sehe, dass Sie bereits dasselbe mit nur einem anderen Variablennamen codiert haben.

    – nnnnn

    27. Dezember 2013 um 10:15 Uhr

  • @nnnnn :) Ja, ich dachte vielleicht reduce könnte eine schöne Alternative sein.

    – Vision

    27. Dezember 2013 um 10:16 Uhr

  • array.reduce((a, e, i) => (e === value) ? a.concat(i) : a, [])

    – yckart

    21. Dezember 2016 um 20:46 Uhr

  • Ich habe gegoogelt contat ist langsamer als pushdeshalb bleibe ich bei der Antwort.

    – André Elrico

    19. September 2019 um 8:16 Uhr

  • Ja, bitte nicht verwenden concat hier – Sie weisen bei jedem Rückruf ein ganz neues Array-Objekt zu und werfen das vorherige Objekt in den Garbage Collector, ohne dass die Lesbarkeit entsprechend verbessert wird.

    – ggorlen

    2. Oktober 2020 um 17:17 Uhr


Benutzeravatar von yckart
yckart

Ein anderer Ansatz mit Array.prototype.map() und Array.prototype.filter():

var indices = array.map((e, i) => e === value ? i : '').filter(String)

  • super, es funktioniert. Können Sie erklären, was die Rolle des Filters ist (String)

    – Muthamischtschelwan. v

    3. Januar 2018 um 19:40 Uhr

  • @Muthu map(…) prüft bei jeder Iteration auf die Gleichheit von e und value. Bei Übereinstimmung wird der Index zurückgegeben, ansonsten ein leerer String. Um diese falschen Werte loszuwerden, filter(String) stellt sicher, dass das Ergebnis nur Werte enthält, die vom Typ Zeichenfolge und NICHT leer sind. filter(String) könnte auch geschrieben werden als: filter(e => e !== '')

    – yckart

    6. Januar 2018 um 19:13 Uhr


  • …oder: String(thing) zwingt irgendetwas zu einer Zeichenfolge. Array#filter gibt ein Array aller Werte zurück, für die die Bedingung gilt Wahrheit. Weil leere Zeichenfolgen sind falschdiese sind NICHT im Array enthalten.

    – yckart

    6. Januar 2018 um 19:13 Uhr


  • Danke für deine Erklärung, das hilft mir wirklich weiter

    – Muthamischtschelwan. v

    7. Januar 2018 um 17:32 Uhr

  • Ich wäre verwirrt, wenn ich das in einem Projekt sehen würde. Es liest sich wie “In Strings filtern”, was bedeutet, nur behalten, wenn es sich um einen String handelt. Und dann wäre das resultierende Array Indizes als Strings, nicht als Zahlen.

    – Michael Pearson

    14. Juli 2019 um 4:08 Uhr

Benutzeravatar von awmidas
awmidas

Einfacher mit dem es6-Stil.

const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);


//Examples:
var cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
indexOfAll(cars, "Nano"); //[0, 3, 5]
indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []

Benutzeravatar von Zac Delventhal
Zac Delventhal

Sie können eine einfach lesbare Lösung dafür schreiben, indem Sie beide verwenden map und filter:

const nanoIndexes = Cars
  .map((car, i) => car === 'Nano' ? i : -1)
  .filter(index => index !== -1);

BEARBEITEN: Wenn Sie IE/Edge nicht unterstützen müssen (oder Ihren Code transpilieren), hat uns ES2019 gegeben flachKartemit dem Sie dies in einem einfachen Einzeiler tun können:

const nanoIndexes = Cars.flatMap((car, i) => car === 'Nano' ? i : []);

  • Ich mochte diese Antwort. Aber wie wäre es mit: Ändern zu diesem: .map((car, i) => car === 'Nano' ? i : null).filter(i => i);

    – Anton vBR

    16. April 2022 um 19:09 Uhr

  • Beides funktioniert. Das Problem bei der Verwendung einer Nichtzahl wie null besteht darin, dass die Eingabe in TypeScript viel lästiger wird. Wenn Sie nur JavaScript verwenden, funktioniert null einwandfrei.

    – Zac Delventhal

    17. April 2022 um 1:31 Uhr

Benutzeravatar von JKhan
JKhan

Ich möchte nur mit einer anderen einfachen Methode aktualisieren.

Sie können auch die forEach-Methode verwenden.

var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];

var result = [];

Cars.forEach((car, index) => car === 'Nano' ? result.push(index) : null)

  • Ich mochte diese Antwort. Aber wie wäre es mit: Ändern zu diesem: .map((car, i) => car === 'Nano' ? i : null).filter(i => i);

    – Anton vBR

    16. April 2022 um 19:09 Uhr

  • Beides funktioniert. Das Problem bei der Verwendung einer Nichtzahl wie null besteht darin, dass die Eingabe in TypeScript viel lästiger wird. Wenn Sie nur JavaScript verwenden, funktioniert null einwandfrei.

    – Zac Delventhal

    17. April 2022 um 1:31 Uhr

Benutzeravatar von abalter
abändern

Hinweis: MDN gibt a Methode mit einer While-Schleife:

var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element="a";
var idx = array.indexOf(element);
while (idx != -1) {
  indices.push(idx);
  idx = array.indexOf(element, idx + 1);
}

Ich würde nicht sagen, dass es besser ist als andere Antworten. Nur interessant.

1438280cookie-checkWie finde ich die Indizes aller Vorkommen eines Elements im Array?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy