Wie finde ich einen Wert in einem Array von Objekten in JavaScript?

90

Ich habe eine Reihe von Objekten:

Object = {
   1 : { name : bob , dinner : pizza },
   2 : { name : john , dinner : sushi },
   3 : { name : larry, dinner : hummus }
}

Ich möchte in der Lage sein, das Objekt / Array nach dem Schlüssel "Abendessen" zu durchsuchen und festzustellen, ob es mit "Sushi" übereinstimmt.

Ich weiß, dass jQuery $ .inArray hat, aber es scheint nicht mit Arrays von Objekten zu funktionieren. Oder vielleicht irre ich mich. indexOf scheint auch nur auf einer Array-Ebene zu funktionieren.

Gibt es dafür keine Funktion oder keinen vorhandenen Code?

Fragesteller
quelle
Dies wurde schon einmal gefragt. Sie müssen Ihre eigene Funktion schreiben oder eine andere Bibliothek verwenden.
Felix Kling
1
Bitte beachten Sie, dass Objectdas in Javascript reservierte ObjectObjekt das Objekt ist, dh die Mutter aller Objekte.
Adamse
1
Frage und akzeptierte Antwort beziehen sich nicht auf mehrdimensionale Arrays, sondern eher auf die eindimensionale Array-Filterung nach den Eigenschaftswerten ihrer Elemente. => Sie haben mein Problem "Finden eines Wertes in einem mehrdimensionalen Array" nicht gelöst.
Martin Schneider

Antworten:

211

Wenn Sie ein Array wie haben

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

Sie können die filterMethode eines Array-Objekts verwenden:

people.filter(function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]

In neueren JavaScript-Implementierungen können Sie einen Funktionsausdruck verwenden:

people.filter(p => p.dinner == "sushi")
  // => [{ "name": "john", "dinner": "sushi" }]

Sie können nach Personen suchen, die "dinner": "sushi"a verwendenmap

people.map(function (person) {
  if (person.dinner == "sushi") {
    return person
  } else {
    return null
  }
}); // => [null, { "name": "john", "dinner": "sushi" }, null]

oder ein reduce

people.reduce(function (sushiPeople, person) {
  if (person.dinner == "sushi") {
    return sushiPeople.concat(person);
  } else {
    return sushiPeople
  }
}, []); // => [{ "name": "john", "dinner": "sushi" }]

Ich bin sicher, dass Sie dies auf beliebige Schlüssel und Werte verallgemeinern können!

adamse
quelle
7
Beachten Sie jedoch, dass diese Lösungen Teil von ECMAScript 5 sind und in IE8 nicht unterstützt werden. kangax.github.com/es5-compat-table So sehr ich die Antwort von @ adamse bevorzuge, ist alex's "old shitty browser" -freundlicher. Ich bin mir jedoch nicht sicher über die Leistung.
EasyCo
@SalmanA - noch bezieht sich die Frage oder die Lösung auf jQuery. Der Javascript-Filter () wird verwendet, nicht jQuery-spezifisch $ .filter () - tutorialspoint.com/javascript/array_filter.htm
Tapirboy
Wie von EasyCo erwähnt, wird die Filterfunktion in IE8 nicht unterstützt. Es kann jedoch problemlos zum Array-Prototyp hinzugefügt und somit in jedem Browser mit einer kleinen Funktion am Anfang Ihrer Skripte verwendet werden. Dies ist in der Filterdokumentation beschrieben . Es gibt die genaue Funktion, die in ECMA-262 angegeben ist, also ist es buchstäblich dasselbe.
Dallas
1
Ich habe gerade eine Antwort hinzugefügt , die die grepMethode von jQuery verwendet. Es könnte sinnvoll sein, in Ihre Antwort zu rollen, da es dasselbe Konzept ist wie das, was Sie tun, aber jQuery-abhängig und scheißbrowserfreundlich.
Zach Lysobey
Gibt es einen Grund, warum ich mit meiner Rückgabevariablen immer wieder einen Referenzfehler erhalte? Ich habe versucht, die beiden besten Antworten mit "x '' zurückzugeben, und es wird immer wieder gesagt, dass es undefiniert ist ...
Evan Lalo
18

jQuery verfügt über eine integrierte Methode jQuery.grep, die ähnlich wie die ES5- filterFunktion von @ adamse's Answer funktioniert und in älteren Browsern einwandfrei funktionieren sollte.

Am Beispiel von adamse:

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

Sie können Folgendes tun

jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]
Zach Lysobey
quelle
10
var getKeyByDinner = function(obj, dinner) {
    var returnKey = -1;

    $.each(obj, function(key, info) {
        if (info.dinner == dinner) {
           returnKey = key;
           return false; 
        };   
    });

    return returnKey;       

}

jsFiddle .

Solange -1es keinen gültigen Schlüssel gibt.

Alex
quelle
beinahe positiv bewertet, aber es gab keine Erklärung in der Post.
Mickmackusa
10

Wenn Sie diese Suche häufig durchführen, sollten Sie das Format Ihres Objekts ändern, damit das Abendessen tatsächlich ein Schlüssel ist. Dies ähnelt dem Zuweisen eines primären Clusterschlüssels in einer Datenbanktabelle. Also zum Beispiel:

Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }

Sie können jetzt einfach so darauf zugreifen: Object['sushi']['name']

Oder wenn das Objekt wirklich so einfach ist (nur 'Name' im Objekt), können Sie es einfach ändern in:

Obj = { 'pizza' : 'bob', 'sushi' : 'john' }

Und dann wie folgt darauf zugreifen : Object['sushi'].

Es ist natürlich nicht immer möglich oder zu Ihrem Vorteil, Ihr Datenobjekt so umzustrukturieren, aber der Punkt ist, manchmal ist die beste Antwort zu überlegen, ob Ihr Datenobjekt am besten strukturiert ist. Das Erstellen eines solchen Schlüssels kann schneller sein und saubereren Code erstellen.

dallin
quelle
1
Ich liebe dich zu antworten, aber ich habe ein Problem mit der Syntax gefunden: meine hat nur so funktioniert: obj = {"pizza": {"name": "bob"}, "sushi": {"name": "john"}} alert ( obj ['pizza'] ['name']); aber dennoch. Vielen Dank! gefunden, wonach ich gesucht habe! )
AleXela
@alexela Danke Alexela! Ich habe meine Antwort mit Ihrer scharfsinnigen Beobachtung aktualisiert! Ich hatte das Beispiel gerade in den Beitrag des OP kopiert und es versäumt, die Anführungszeichen hinzuzufügen, aber Sie haben Recht - es funktioniert nur, wenn es zumindest Anführungszeichen um die Werte gibt (vorausgesetzt, es handelt sich um Werte und nicht um Variablen).
Dallas
3

Sie finden das Objekt im Array mit der Alasql- Bibliothek:

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

var res = alasql('SELECT * FROM ? WHERE dinner="sushi"',[data]);

Versuchen Sie dieses Beispiel in jsFiddle .

Agershun
quelle
3
Ich bin mir nicht sicher, ob dies wirklich eine Abstimmung verdient hat. SQL-ähnliche Abfragen zu Sammlungen lassen sich viel einfacher begründen und schreiben, wenn die Anforderungen komplizierter werden als ein einzelner Filter oder eine Reduzierung des Aufrufs. Alasql ist eine ziemlich beeindruckende Bibliothek, aber zugegebenermaßen ein wenig übertrieben für das obige Beispiel.
TomDotTom
1
Wenn das Objekt selbst aus einer SQL-Quelle stammt, ist diese Antwort ein Genie.
edwardsmarkf
1

Sie können eine einfache for in-Schleife verwenden:

for (prop in Obj){
    if (Obj[prop]['dinner'] === 'sushi'){

        // Do stuff with found object. E.g. put it into an array:
        arrFoo.push(Obj[prop]);
    }
}

Das folgende Geigenbeispiel fügt alle Objekte, die enthalten sind, dinner:sushiin ein Array ein:

https://jsfiddle.net/3asvkLn6/1/

Rotareti
quelle
1

Hier gibt es bereits viele gute Antworten. Warum also nicht noch eine? Verwenden Sie eine Bibliothek wie lodash oder Unterstrich :)

obj = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
}

_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]
TomDotTom
quelle
0

Ich musste eine verschachtelte Sitemap-Struktur nach dem ersten Blattelement durchsuchen, das einen bestimmten Pfad erstellt. Ich habe den folgenden Code nur mit .map() .filter()und entwickelt .reduce. Gibt das zuletzt gefundene Element zurück, das dem Pfad entspricht /c.

var sitemap = {
  nodes: [
    {
      items: [{ path: "/a" }, { path: "/b" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    }
  ]
};

const item = sitemap.nodes
  .map(n => n.items.filter(i => i.path === "/c"))
  .reduce((last, now) => last.concat(now))
  .reduce((last, now) => now);

Bearbeiten Sie 4n4904z07

Marc
quelle
0

Ich würde versuchen, das Rad nicht neu zu erfinden. Wir verwenden den Objekt-Scan für alle unsere Datenverarbeitungsanforderungen. Es ist konzeptionell sehr einfach, erlaubt aber viele coole Sachen. So würden Sie Ihre spezifische Frage lösen

Datendefinition

const data = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
};

Logik

const objectScan = require('object-scan');

const scanner = (input) => {
  let obj = null;
  objectScan(['*.dinner'], {
    filterFn: (key, value, { parents }) => {
      if (value === 'sushi') {
        obj = parents[0];
      }
    },
    breakFn: () => obj !== null
  })(data);
  return obj;
};

const result = scanner(data);

Ausgabe

// => result
{
  "name": "john",
  "dinner": "sushi"
}
Vincent
quelle
0

Wenn Sie ein bestimmtes Objekt über die Suchfunktion finden möchten, versuchen Sie einfach Folgendes:

    function findArray(value){

        let countLayer = dataLayer.length;
        for(var x = 0 ; x < countLayer ; x++){

            if(dataLayer[x].user){
                let newArr = dataLayer[x].user;
                let data = newArr[value];
                return data;
            }

        }

        return null;

    }

    findArray("id");

Dies ist ein Beispielobjekt:

layerObj = {
    0: { gtm.start :1232542, event: "gtm.js"},
    1: { event: "gtm.dom", gtm.uniqueEventId: 52},
    2: { visitor id: "abcdef2345"},
    3: { user: { id: "29857239", verified: "Null", user_profile: "Personal", billing_subscription: "True", partners_user: "adobe"}
}

Der Code iteriert und findet das "Benutzer" -Array und sucht nach dem Objekt, das Sie darin suchen.

Mein Problem war, als der Array-Index bei jeder Fensteraktualisierung geändert wurde und sich entweder im 3. oder im zweiten Array befand, aber das spielt keine Rolle.

Arbeitete wie ein Zauber für mich!

In Ihrem Beispiel ist es etwas kürzer:

function findArray(value){

    let countLayer = Object.length;
    for(var x = 0 ; x < countLayer ; x++){

        if(Object[x].dinner === value){
            return Object[x];
        }

    }

    return null;

}

findArray('sushi');
z3r0
quelle