So finden Sie den Index eines Objekts nach Schlüssel und Wert in einem Javascript-Array

74

Gegeben:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

Gesucht:

Index des Objekts wo attr === valuezum Beispiel attr1 === "john"oderattr2 === "hummus"

Update: Bitte lesen Sie meine Frage sorgfältig durch. Ich möchte das Objekt weder über $ .inArray finden noch den Wert eines bestimmten Objektattributs abrufen. Bitte berücksichtigen Sie dies für Ihre Antworten. Vielen Dank!

return1.at
quelle
1
Mögliches Duplikat von Objekt suchen durch ID in Array von Javascript-Objekten
Felix Kling
2
Ja, der gleiche Anwendungsfall, aber ich finde meine Frage allgemeiner, z. B. eine bessere Trefferquote, wenn Sie keinen Schlüssel mit dem Namen "id" haben, nach dem Sie suchen.
return1.at
@FelixKling Ich denke nicht, dass dies ein Duplikat ist, weil es versucht, den Index im Gegensatz zum Objekt zu erhalten (die Frage, auf die Sie zeigen, hat mein Problem nicht gelöst, aber diese hat es getan).
Jcuenod

Antworten:

153

Der funktionale Ansatz

Alle coolen Kids machen heutzutage funktionale Programmierung ( Hallo React-Benutzer ), also dachte ich, ich würde die funktionale Lösung geben. Meiner Ansicht nach ist es tatsächlich viel schöner als das bisher vorgeschlagene Imperatival forund die eachLoops, und mit der ES6-Syntax ist es ziemlich elegant.

Aktualisieren

Es gibt jetzt eine großartige Möglichkeit, dies zu tun, findIndexdie eine Funktion übernimmt, die zurückgibt true/ darauf falsebasiert, ob das Array-Element übereinstimmt (wie immer jedoch auf Browserkompatibilität prüfen).

var index = peoples.findIndex(function(person) {
  return person.attr1 == "john"
}

Mit der ES6-Syntax können Sie Folgendes schreiben:

var index = peoples.findIndex(p => p.attr1 == "john")

Der (alte) funktionale Ansatz

TL; DR

Wenn Sie suchen, indexwo Sie peoples[index].attr1 == "john"verwenden können:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

Erläuterung

Schritt 1

Verwenden Sie .map()diese Option , um ein Array von Werten für einen bestimmten Schlüssel abzurufen:

var values = object_array.map(function(o) { return o.your_key; });

Die obige Zeile führt Sie von hier aus:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

Bis hierhin:

var values = [ "bob", "john", "larry" ];

Schritt 2

Jetzt verwenden wir nur .indexOf()noch den Index des gewünschten Schlüssels (der natürlich auch der Index des gesuchten Objekts ist):

var index = values.indexOf(your_value);

Lösung

Wir kombinieren alle oben genannten:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

Oder wenn Sie die ES6-Syntax bevorzugen:

var index = peoples.map((o) => o.attr1).indexOf("john");

Demo:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");
console.log("index of 'john': " + index);

var index = peoples.map((o) => o.attr1).indexOf("larry");
console.log("index of 'larry': " + index);

var index = peoples.map(function(o) { return o.attr1; }).indexOf("fred");
console.log("index of 'fred': " + index);

var index = peoples.map((o) => o.attr2).indexOf("pizza");
console.log("index of 'pizza' in 'attr2': " + index);

jcuenod
quelle
Ich bin traurig, dass der IE die findIndexFunktion nicht unterstützt .
Wonsuc
Nehmen wir nun an, Sie wollten den Index der Pizza innerhalb der Zeile wissen { "attr1": "bob", "attr2": "pizza" }, das ist "1". Wie würden Sie das tun? Oder wie würden Sie das tun, wenn Sie den Wert "pizza"wissen property namemöchten , der der entsprechende Wert ist (dh attr2), wenn wir uns in Zeile 0 befinden?
John Galassi
Vielleicht ist es aktualisiert. findIndexGibt jetzt -1 oder gefundene Indexposition zurück.
Volkan Güven
20

Wenn Sie das Objekt selbst überprüfen möchten, ohne den Prototyp zu beeinträchtigen, verwenden Sie hasOwnProperty():

var getIndexIfObjWithOwnAttr = function(array, attr, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i].hasOwnProperty(attr) && array[i][attr] === value) {
            return i;
        }
    }
    return -1;
}

Verwenden Sie Folgendes, um auch Prototypattribute einzuschließen:

var getIndexIfObjWithAttr = function(array, attr, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i][attr] === value) {
            return i;
        }
    }
    return -1;
}
return1.at
quelle
1
+1, aber warum nicht einfach i zurückgeben (anstelle von $ .inArray (Array [i], Array);)?
Me.Name
1
Warum benutzt du i += 1statt i++?
Amberlamps
1
Warum sollte 'array [i] .hasOwnProperty (attr)' anstelle von 'array [i] [attr]' verwendet werden?
Alain BECKER
@ AlainSaint-Etienne siehe stackoverflow.com/questions/135448/…
return1.at
1
Ich schlage vor, 'return -1' nach der 'for'-Schleife hinzuzufügen, falls das Element nicht gefunden wurde (ähnlich wie' indexOf 'von javascript oder' $ .inArray 'von jquery)
schellmax
8

Verwenden von jQuery .each ()

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

$.each(peoples, function(index, obj) {
   $.each(obj, function(attr, value) {
      console.log( attr + ' == ' + value );
   });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Verwendung for-Schleife :

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

for (var i = 0; i < peoples.length; i++) {
  for (var key in peoples[i]) {
    console.log(key + ' == ' + peoples[i][key]);
  }
}

thecodeparadox
quelle
Links sind kaputt Alexander
Alexander
4

Keine direkte Antwort auf Ihre Frage, obwohl ich denke, dass es erwähnenswert ist, sie zu erwähnen, da Ihre Frage im allgemeinen Fall "Dinge mit Namen in einem Schlüsselwertspeicher abrufen" zu passen scheint.

Wenn Sie nicht genau wissen, wie "Völker" implementiert werden, ist eine JavaScript-artigere Methode, um den richtigen Mann zu finden, möglicherweise:

var peoples = {
  "bob":  { "dinner": "pizza" },
  "john": { "dinner": "sushi" },
  "larry" { "dinner": "hummus" }
};

// If people is implemented this way, then
// you can get values from their name, like :
var theGuy = peoples["john"];

// You can event get directly to the values
var thatGuysPrefferedDinner = peoples["john"].dinner;

Hoffe, wenn dies nicht die Antwort ist, die Sie wollten, könnte es Menschen helfen, die an dieser "Schlüssel / Wert" -Frage interessiert sind.

Alain BECKER
quelle
Das trifft meinen Anwendungsfall nicht, ist aber vielleicht für andere hilfreich. Ich sollte meine Frage für allgemeinere Attributnamen aktualisieren, um dies klar zu machen.
return1.at
3
function getIndexByAttribute(list, attr, val){
    var result = null;
    $.each(list, function(index, item){
        if(item[attr].toString() == val.toString()){
           result = index;
           return false;     // breaks the $.each() loop
        }
    });
    return result;
}
David
quelle
Nur um eines zu klären: 'return false' scheint unnötig. Man kann darauf verzichten, aber es ist eine gute Optimierung, da es die '$ .each ()' - Schleife durchbricht. Gut gemacht! Auf der anderen Seite ist der Aufruf von '.toString ()' seltsam (warum nicht Werte vergleichen?) Und verursacht wahrscheinlich einen Fehler, wenn 'attr' für 'item' undefiniert ist oder wenn val 'null' ist. Oder habe ich einen sehr guten Grund verpasst, hier 'toString ()' zu verwenden?
Alain BECKER
Ich erinnere mich nicht genau, warum ich diesen Weg gegangen bin, aber ich erinnere mich an einen Konflikt, als der Wert eine Zahl war
David
1

Gehen Sie folgendermaßen vor:

var peoples = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

$.each(peoples, function(i, val) {
    $.each(val, function(key, name) {
        if (name === "john")
            alert(key + " : " + name);
    });
});

AUSGABE:

name : john

Siehe LIVE DEMO

Siva Charan
quelle
1
Absolut keine Notwendigkeit für jQuery.
Lukas
1

Sie können es auch zu einer wiederverwendbaren Methode machen, indem Sie JavaScript verwenden:

Array.prototype.findIndexBy = function(key, value) {
    return this.findIndex(item => item[key] === value)
}

const peoples = [{name: 'john'}]
const cats = [{id: 1, name: 'kitty'}]

peoples.findIndexBy('name', 'john')
cats.findIndexBy('id', 1)

Tycho
quelle