Wie kann festgestellt werden, ob das Javascript-Array ein Objekt mit einem Attribut enthält, das einem bestimmten Wert entspricht?

655

Ich habe ein Array wie

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } //and so on goes array... 
];

Wie überprüfe ich dieses Array, um festzustellen, ob Magenic vorhanden ist? Ich möchte keine Schleife machen, es sei denn, ich muss. Ich arbeite mit möglicherweise ein paar tausend Datensätzen.


AKTUALISIERT

Da dies ein beliebter Beitrag war, dachte ich, ich würde etwas Neues teilen, das ich gefunden habe. Und es scheint, dass @CAFxX dies bereits geteilt hat! Ich sollte diese öfter lesen. Ich bin auf https://benfrain.com/understanding-native-javascript-array-methods/ gestoßen .

vendors.filter(function(vendor){ return vendor.Name === "Magenic" })

Mit ECMAScript 2015 ist die Verwendung der neuen Pfeilfunktionen noch einfacher:

vendors.filter(vendor => vendor.Name === "Magenic")
David Lozzi
quelle
Bitte entschuldigen Sie den scheinbar zufälligen Kommentar, aber betraf Ihre Frage JSON oder nur JavaScript-Arrays?
Alex Turpin
4
@CAFxX-Lösung ist besser, wäre fantastisch, wenn Sie die ausgewählte Lösung aktualisieren.
eMarine
1
Einverstanden, habe das nicht früher gesehen!
David Lozzi
Sie können dies jetzt noch mehr vereinfachen, indem Sie Pfeilfunktionen verwenden. Alle modernen Browser unterstützen dies und sehen besser aus.
Piotr Kula
Sie können Kartenfunktion verwenden, sehr nützlich
Monir alhussini

Antworten:

264

Bearbeiten 2018 : Diese Antwort stammt aus dem Jahr 2011, bevor Browser Array-Filtermethoden und Pfeilfunktionen weitgehend unterstützt hatten. Schauen Sie sich die Antwort von CAFxX an .

Es gibt keine "magische" Möglichkeit, in einem Array ohne Schleife nach etwas zu suchen. Selbst wenn Sie eine Funktion verwenden, verwendet die Funktion selbst eine Schleife. Was Sie tun können, ist aus der Schleife auszubrechen, sobald Sie das finden, wonach Sie suchen, um die Rechenzeit zu minimieren.

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}
Alex Turpin
quelle
4
Kein Problem. Denken Sie daran, dass die Lösung von Keith auch sehr praktikabel ist und Sie vor Schleifen bewahrt.
Alex Turpin
2
Sie benötigen kein Flag, wenn Sie nur wissen müssen, ob "etwas" vorhanden ist oder nicht. Sie können einfach den Wert des Scan-Index anhand der Größe des Arrays überprüfen. Damit dies funktioniert, muss der Index var natürlich vor der for-Anweisung deklariert werden.
Alex
5
Diese Optionen scheinen jetzt zu funktionieren: vendor.forEach, vendor.filter, vendor.reduce
David Lozzi
1
Was ist mit JSON.stringify (Anbieter) .indexOf ('Magenic')! == -1
Letzter Atemzug
1
@ LastBreath, die ziemlich leicht zu einem falschen Positiv führen kann, wenn 'Magenic'es sich irgendwo anders im Objekt befindet
Alex Turpin
945

Keine Notwendigkeit, das neu zu erfinden RadSchleife, zumindest nicht explizit (mit Pfeilfunktionen , nur moderne Browser ):

if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
  /* vendors contains the element we're looking for */
}

oder noch besser :

if (vendors.some(e => e.Name === 'Magenic')) {
  /* vendors contains the element we're looking for */
}

BEARBEITEN: Wenn Sie Kompatibilität mit miesen Browsern benötigen, ist Ihre beste Wahl:

if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
  /* vendors contains the element we're looking for */
}
CAFxX
quelle
4
@Rocket warum hast du meine Antwort bearbeitet? Die Syntax ohne geschweifte Klammern ist perfekt gültiges Javascript .
CAFxX
4
Die "Lambda" -Syntax funktioniert in Chrome 16 (das ist kein mieser Browser) immer noch nicht.
Rocket Hazmat
27
Es hängt von Ihrer Definition von mies ab, denke ich. Diese Syntax ist Teil von Javascript 1.8.
CAFxX
7
Die Ausdrucksverschlüsse, die Sie hier im ersten und zweiten Beispiel verwenden, haben einen Nicht-Standard, nicht verwenden! Warnung von Mozilla (siehe diesen Link). Sie haben bisher nur in Firefox funktioniert und sind jetzt veraltet und werden zugunsten von Pfeilfunktionen entfernt .
Doppelgreener
2
@ 7hibault, da ein someKurzschluss auftreten kann, sobald ein Objekt mit name === "Magenic"gefunden wurde. Mit filterüberprüft es jedes Element bis zum Ende des Arrays und erstellt ein neues Array-Element, das der Bedingung entspricht, und überprüft dann dielength
Adiga
92

Keine Schleife notwendig. Drei Methoden, die mir in den Sinn kommen:

Array.prototype.some ()

Dies ist die genaueste Antwort auf Ihre Frage, dh "Überprüfen Sie, ob etwas vorhanden ist", was ein booles Ergebnis impliziert. Dies ist wahr, wenn es 'Magen'-Objekte gibt, andernfalls falsch:

let hasMagenicVendor = vendors.some( vendor => vendor['Name'] === 'Magenic' )

Array.prototype.filter ()

Dies gibt ein Array aller 'Magenic'-Objekte zurück, auch wenn es nur eines gibt (gibt ein Ein-Element-Array zurück):

let magenicVendors = vendors.filter( vendor => vendor['Name'] === 'Magenic' )

Wenn Sie versuchen, dies zu einem Booleschen Wert zu erzwingen, funktioniert dies nicht, da ein leeres Array (keine 'Magen'-Objekte) immer noch wahr ist. Also einfach magenicVendors.lengthin deiner Bedingung verwenden.

Array.prototype.find ()

Dies gibt das erste 'Magenic'-Objekt zurück (oder undefinedfalls es keine gibt):

let magenicVendor = vendors.find( vendor => vendor['Name'] === 'Magenic' );

Dies zwingt zu einem booleschen Okay (jedes Objekt ist wahr, undefinedist falsch).


Hinweis: Ich verwende den Anbieter ["Name"] anstelle des Anbieters. Name wegen der seltsamen Schreibweise der Eigenschaftsnamen.

Hinweis 2: Kein Grund, bei der Überprüfung des Namens lose Gleichheit (==) anstelle von strikter Gleichheit (===) zu verwenden.

Boxtrain
quelle
5
Es ist nützlich darauf hinzuweisen, dass sich unter der Haube alle Schleifen befinden. Diese sind auch alle rechnerisch langsamer als nur zum Schleifen und Ausführen von Operationen.
ThePartyTurtle
Kann auch diese Liebe hier teilen: stackoverflow.com/questions/21748670/… damit mehr Leute wie ich nicht zu dieser alten Seite navigieren und Annahmen treffen.
ThePartyTurtle
43

Die akzeptierte Antwort funktioniert immer noch, aber jetzt haben wir eine native ECMAScript 6-Methode [Array.find][1], um den gleichen Effekt zu erzielen.

MDN zitieren:

Die find () -Methode gibt den Wert des ersten Elements im Array zurück, das die bereitgestellte Testfunktion erfüllt. Andernfalls wird undefined zurückgegeben.

var arr = []; 
var item = {
  id: '21',
  step: 'step2',
  label: 'Banana',
  price: '19$'
};

arr.push(item);
/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */
var data = arr.find( function( ele ) { 
    return ele.id === '21';
} );

if( data ) {
 console.log( 'found' );
 console.log(data); // This is entire object i.e. `item` not boolean
}

Siehe meinen jsfiddle-Link. Es gibt eine Polyfüllung für IE, die von Mozilla bereitgestellt wird

Teekocher
quelle
2
Könnte kürzer sein, wenn Sie dies nur tun return ele.id == '2', aber +1 für eine gute ES6-Lösung.
Lye Fish
Gut, eine neue Antwort zu haben :)
Ich
Ich denke, es ist wichtig darauf hinzuweisen, dass der Rückgabewert von 'data' (wenn ele.id mit einer ID wie '21' übereinstimmt) das Array-Element selbst sein wird (in diesem Fall das gesamte Elementobjekt). Wenn die Erwartung wäre, dass das Ergebnis der Datenvariablen "wahr" oder "falsch" anstelle eines falschen Wertes ist, wären Sie zutiefst enttäuscht.
Adamgede
Danke! Meine Aufgabe war etwas anders. Holen Sie sich den Index des Objekts im Array => push if <0 || splice(index, 1)hier ist mein etwas aktualisierter Code:const index = this.selected.indexOf(this.selected.find(s => s.id == passedObj.id))
Leonid Zadorozhnykh
29

So würde ich es machen

const found = vendors.some(item => item.Name === 'Magenic');

array.some()Die Methode prüft, ob ein Array mindestens einen Wert enthält, der den Kriterien entspricht, und gibt einen Booleschen Wert zurück. Ab hier können Sie gehen mit:

if (found) {
// do something
} else {
// do something else
}
Mirza Leka
quelle
22

Es sei denn, Sie möchten es wie folgt umstrukturieren:

vendors = {
    Magenic: {
      Name: 'Magenic',
      ID: 'ABC'
     },
    Microsoft: {
      Name: 'Microsoft',
      ID: 'DEF'
    } and so on... 
};

was du tun kannst if(vendors.Magnetic)

Sie müssen eine Schleife durchführen

Keith.Abramo
quelle
2
Für den Fall, dass er die Objektstruktur noch beibehalten wollte, um sie woanders zu verwenden
Keith.Abramo
21

Gemäß der ECMAScript 6-Spezifikation können Sie verwenden findIndex.

const magenicIndex = vendors.findIndex(vendor => vendor.Name === 'Magenic');

magenicIndexwird entweder halten 0(das ist der Index im Array) oder -1wenn es nicht gefunden wurde.

Lucas Bento
quelle
Nur um die Leute darauf aufmerksam zu machen, dass 0 immer noch als falsches Ergebnis übereinstimmt, wenn dies als Bedingung verwendet wird. Aus diesem Grund denke ich, dass find () besser ist, wenn Sie eine logischere Bewertung der Wahrheit erhalten.
Dhj
15

Da hat das OP die Frage gestellt, ob der Schlüssel existiert oder nicht .

Eine elegantere Lösung, die mit der ES6-Reduktionsfunktion einen Booleschen Wert zurückgibt, kann sein

const magenicVendorExists =  vendors.reduce((accumulator, vendor) => (accumulator||vendor.Name === "Magenic"), false);

Hinweis: Der Anfangsparameter von reduct ist a. falseWenn das Array den Schlüssel hat, wird true zurückgegeben.

Hoffe, es hilft für eine bessere und sauberere Code-Implementierung

Jay Chakra
quelle
1
Seit wann ist !! [] gleich falsch?
Sergey
1
Schöner Fang. Aktualisierte Antwort mit reduzieren :)
Jay Chakra
1
Das ist falsch. Der erste Parameter reduceist der Akkumulator und nicht das vendorObjekt. Dies prüft false.Name === "Magenic"jede Schleife und gibt false zurück
adiga
@adiga: Korrigiert.
Jay Chakra
1
Bitte überprüfen Sie auch die Lösung von Mirza Leka. Eine viel elegantere Lösung.
Jay Chakra
13

Sie können nicht, ohne wirklich in das Objekt zu schauen.

Sie sollten wahrscheinlich Ihre Struktur ein wenig ändern, wie

vendors = {
    Magenic:   'ABC',
    Microsoft: 'DEF'
};

Dann können Sie es einfach wie einen Lookup-Hash verwenden.

vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined
jAndy
quelle
5

Sie müssen eine Schleife machen, daran führt kein Weg vorbei.

function seekVendor(vendors, name) {
  for (var i=0, l=vendors.length; i<l; i++) {
    if (typeof vendors[i] == "object" && vendors[i].Name === name) {
      return vendors[i];
    }
  }
}

Natürlich können Sie eine Bibliothek wie linq.js verwenden , um dies angenehmer zu gestalten:

Enumerable.From(vendors).Where("$.Name == 'Magenic'").First();

( Eine Demo finden Sie unter jsFiddle. )

Ich bezweifle, dass linq.js schneller sein wird als eine einfache Schleife, aber es ist sicherlich flexibler, wenn die Dinge etwas komplizierter werden.

Tomalak
quelle
5

Testen auf Array-Elemente:

JS Bietet Array-Funktionen, mit denen Sie dies relativ einfach erreichen können. Sie sind die folgenden:

  1. Array.prototype.filter: Nimmt eine Rückruffunktion auf, die ein Test ist, wird das Array dann mit dem Rückruf iteriert und gemäß diesem Rückruf gefiltert. Ein neues gefiltertes Array wird zurückgegeben.
  2. Array.prototype.some: Nimmt eine Rückruffunktion auf, die ein Test ist, das Array wird dann mit dem Rückruf iteriert, und wenn ein Element den Test besteht, wird der boolesche Wert true zurückgegeben. Andernfalls wird false zurückgegeben

Die Einzelheiten lassen sich am besten anhand eines Beispiels erklären:

Beispiel:

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } //and so on goes array... 
];

// filter returns a new array, we instantly check if the length 
// is longer than zero of this newly created array
if (vendors.filter(company => company.Name === 'Magenic').length ) {
  console.log('I contain Magenic');
}

// some would be a better option then filter since it directly returns a boolean
if (vendors.some(company => company.Name === 'Magenic')) {
  console.log('I also contain Magenic');
}

Browserunterstützung:

Diese 2 Funktionen sind ES6Funktionen, die möglicherweise nicht von allen Browsern unterstützt werden. Um dies zu überwinden, können Sie eine Polyfüllung verwenden. Hier ist die Polyfüllung für Array.prototype.some(von MDN):

if (!Array.prototype.some) {
  Array.prototype.some = function(fun, thisArg) {
    'use strict';

    if (this == null) {
      throw new TypeError('Array.prototype.some called on null or undefined');
    }

    if (typeof fun !== 'function') {
      throw new TypeError();
    }

    var t = Object(this);
    var len = t.length >>> 0;

    for (var i = 0; i < len; i++) {
      if (i in t && fun.call(thisArg, t[i], i, t)) {
        return true;
      }
    }

    return false;
  };
}

Willem van der Veen
quelle
5

Möglicherweise ist es zu spät, aber das Javascript-Array verfügt über zwei Methoden someund everyMethoden, die einen Booleschen Wert zurückgeben und Ihnen dabei helfen können.

Ich denke, es somewäre am besten geeignet für das, was Sie erreichen wollen.

vendors.some( vendor => vendor['Name'] !== 'Magenic' )

Einige überprüfen, ob eines der Objekte im Array die angegebene Bedingung erfüllt.

vendors.every( vendor => vendor['Name'] !== 'Magenic' )

Jeder überprüft, ob alle Objekte im Array die angegebene Bedingung erfüllen.

Akinjiola Toni
quelle
Es funktioniert nicht, const array1 = [{name:'Mike'},{name:'Alice'}]; console.log(array1.every(item => item.name !== 'Mike'));es sollte wahr sein
Thanwa Ch.
Sorry Kumpel, ich meinte, ich somewerde meine Antwort aktualisieren.
Akinjiola Toni
4

Wenn Sie jquery verwenden, können Sie grep nutzen, um ein Array mit allen übereinstimmenden Objekten zu erstellen:

var results = $.grep(vendors, function (e) {
    return e.Name == "Magenic";
});

und verwenden Sie dann das Ergebnisarray:

for (var i=0, l=results.length; i<l; i++) {
    console.log(results[i].ID);
}
Eitan
quelle
3

Korrigieren Sie mich, wenn ich falsch liege. Ich hätte eine forEachMethode wie diese verwenden können.

var found=false;
vendors.forEach(function(item){
   if(item.name === "name"){
       found=true;

   }
});

Heutzutage bin ich daran gewöhnt, weil es einfach und selbsterklärend ist. Vielen Dank.

Siddhesh Mishra
quelle
1
Hinweis: Keine Verwendung der Rückgabe hier
Edison
2

Sie können dies seine Arbeit für mich versuchen.

const _ = require('lodash');

var arr = [
  {
    name: 'Jack',
    id: 1
  },
  {
    name: 'Gabriel',
    id: 2
  },
  {
    name: 'John',
    id: 3
  }
]

function findValue(arr,value) {
  return _.filter(arr, function (object) {
    return object['name'].toLowerCase().indexOf(value.toLowerCase()) >= 0;
  });
}

console.log(findValue(arr,'jack'))
//[ { name: 'Jack', id: 1 } ]
jenish
quelle
Nun, das ist eine wirklich alte Frage und ich denke, das Update hat heutzutage bereits die beste Lösung.
Federico Galfione
1

Sie können lodash verwenden . Wenn die lodash-Bibliothek für Ihre Anwendung zu schwer ist, sollten Sie unnötige Funktionen entfernen, die nicht verwendet werden.

let newArray = filter(_this.props.ArrayOne, function(item) {
                    return find(_this.props.ArrayTwo, {"speciesId": item.speciesId});
                });

Dies ist nur eine Möglichkeit, dies zu tun. Ein anderer kann sein:

var newArray=  [];
     _.filter(ArrayOne, function(item) {
                        return AllSpecies.forEach(function(cItem){
                            if (cItem.speciesId == item.speciesId){
                            newArray.push(item);
                          }
                        }) 
                    });

console.log(arr);

Das obige Beispiel kann auch ohne Verwendung von Bibliotheken wie den folgenden umgeschrieben werden :

var newArray=  [];
ArrayOne.filter(function(item) {
                return ArrayTwo.forEach(function(cItem){
                    if (cItem.speciesId == item.speciesId){
                    newArray.push(item);
                  }
                }) 
            });
console.log(arr);

Hoffe meine Antwort hilft.

Abhay Shiro
quelle
1

Viele Antworten hier sind gut und ziemlich einfach. Wenn Ihr Objektarray jedoch einen festen Wertesatz hat, können Sie den folgenden Trick verwenden:

Ordnen Sie den gesamten Namen eines Objekts zu.

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

var dirtyObj = {}
for(var count=0;count<vendors.length;count++){
   dirtyObj[vendors[count].Name] = true //or assign which gives you true.
}

Jetzt können Sie dieses DirtyObj immer wieder ohne Schleife verwenden.

if(dirtyObj[vendor.Name]){
  console.log("Hey! I am available.");
}
Jesusverma
quelle
1

Um ein Objekt mit einem anderen zu vergleichen, kombiniere ich eine for in-Schleife (zum Durchlaufen von Objekten) und some (). Sie müssen sich keine Sorgen machen, dass ein Array außerhalb der Grenzen usw. liegt, sodass Code gespart wird. Dokumentation zu .some finden Sie hier

var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];    
var  objectsFound = [];

for(let objectNumber in productList){
    var currentId = productList[objectNumber].id;   
    if (theDatabaseList.some(obj => obj.id === currentId)) {
        // Do what you need to do with the matching value here
        objectsFound.push(currentId);
    }
}
console.log(objectsFound);

Eine alternative Möglichkeit, ein Objekt mit einem anderen zu vergleichen, besteht darin, eine verschachtelte for-Schleife mit Object.keys (). Length zu verwenden, um die Anzahl der Objekte im Array abzurufen. Code unten:

var productList = [{id: 'text3'}, {id: 'text2'}, {id: 'text4', product: 'Shampoo'}]; // Example of selected products
var theDatabaseList = [{id: 'text1'}, {id: 'text2'},{id: 'text3'},{id:'text4', product: 'shampoo'}];    
var objectsFound = [];

for(var i = 0; i < Object.keys(productList).length; i++){
        for(var j = 0; j < Object.keys(theDatabaseList).length; j++){
        if(productList[i].id === theDatabaseList[j].id){
            objectsFound.push(productList[i].id);
        }       
    }
}
console.log(objectsFound);

Um Ihre genaue Frage zu beantworten: Wenn Sie nur nach einem Wert in einem Objekt suchen, können Sie eine einzelne for-Schleife verwenden.

var vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    } 
];

for(var ojectNumbers in vendors){
    if(vendors[ojectNumbers].Name === 'Magenic'){
        console.log('object contains Magenic');
    }
}
Flitter
quelle
0

Alternativ können Sie Folgendes tun:

const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));
BrunoWest
quelle
1
Sie sollten besser sagen, warum er das kann
Azzabi Haythem
0

var without2 = (arr, args) => arr.filter(v => v.id !== args.id); Beispiel:

without2([{id:1},{id:1},{id:2}],{id:2})

Ergebnis: ohne2 ([{id: 1}, {id: 1}, {id: 2}], {id: 2})

behzad abbasi
quelle
Ich denke, Sie wollten Ergebnis sagen: [{id: 1}, {id: 1}]
Isaac Pak
0
const a = [{one:2},{two:2},{two:4}]
const b = a.filter(val => "two" in val).length;
if (b) {
   ...
}
user1665355
quelle
3
Bitte und eine Beschreibung und stellen Sie sicher, dass das von Ihnen bereitgestellte Beispiel funktioniert. (Der Filter ändert das ursprüngliche Array nicht, sondern klont es.)
Moshe Simantov
-1

Mein Ansatz zur Lösung dieses Problems besteht darin, ES6 zu verwenden und eine Funktion zu erstellen, die die Prüfung für uns durchführt. Der Vorteil dieser Funktion besteht darin, dass sie in Ihrem gesamten Projekt wiederverwendet werden kann, um alle Arrays von Objekten zu überprüfen , die mit keyund valueüberprüft werden sollen.

GENUG SPRECHEN, SEHEN WIR DEN CODE

Array

const ceos = [
  {
    name: "Jeff Bezos",
    company: "Amazon"
  }, 
  {
    name: "Mark Zuckerberg",
    company: "Facebook"
  }, 
  {
    name: "Tim Cook",
    company: "Apple"
  }
];

Funktion

const arrayIncludesInObj = (arr, key, valueToCheck) => {
  let found = false;

  arr.some(value => {
    if (value[key] === valueToCheck) {
      found = true;
      return true; // this will break the loop once found
    }
  });

  return found;
}

Anruf / Nutzung

const found = arrayIncludesInObj(ceos, "name", "Tim Cook"); // true

const found = arrayIncludesInObj(ceos, "name", "Tim Bezos"); // false
Rotimi-am besten
quelle
-4

Ich würde lieber mit Regex gehen.

Wenn Ihr Code wie folgt lautet:

vendors = [
    {
      Name: 'Magenic',
      ID: 'ABC'
     },
    {
      Name: 'Microsoft',
      ID: 'DEF'
    }
];

ich würde empfehlen

/"Name":"Magenic"/.test(JSON.stringify(vendors))
Sangwook Kim
quelle
23
Einige Leute denken, wenn sie mit einem Problem konfrontiert werden: "Ich weiß, ich werde reguläre Ausdrücke verwenden." Jetzt haben sie zwei Probleme.
Craicerjack
Datei dies unter, nur weil Sie etwas tun können, bedeutet nicht, dass Sie sollten.
Liam