Hvordan avgjøre om et JavaScript-array inneholder et objekt med en attributt som er lik en gitt verdi


Jeg har et array som

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

Hvordan sjekker jeg dette arrayet for å se om "Magenic" finnes? Jeg vil ikke bruke en løkke, med mindre jeg må. Jeg jobber med potensielt et par tusen poster.

Svar #1

Det er ikke nødvendig å oppfinne hjulet-loopen på nytt, i det minste ikke eksplisitt.

Bruk some da det lar nettleseren stoppe så snart ett element finnes som passer:

if (vendors.some(e => e.Name === 'Magenic')) {
  // We found at least one object that we're looking for!
}

eller tilsvarende (i dette tilfellet) med find, som returnerer det funne objektet i stedet for en boolsk verdi:

if (vendors.find(e => e.Name === 'Magenic')) {
  // Usually the same result as above, but find returns the element itself
}

Hvis du vil finne posisjonen til det elementet, bruk findIndex:

const i = vendors.findIndex(e => e.Name === 'Magenic');
if (i > -1) {
  // We know that at least 1 object that matches has been found at the index i
}

Hvis du trenger å få alle objektene som matcher:

if (vendors.filter(e => e.Name === 'Magenic').length > 0) {
  // The same result as above, but filter returns all objects that match
}

Hvis du trenger kompatibilitet med veldig gamle nettlesere som ikke støtter pilfunksjoner, er ditt beste valg:

if (vendors.filter(function(e) { return e.Name === 'Magenic'; }).length > 0) {
  // The same result as above, but filter returns all objects that match and we avoid an arrow function for compatibility
}

Svar #2

2018 redigering: Dette svaret er fra 2011, før nettlesere hadde bred støtte for array-filtreringsmetoder og pilfunksjoner. Ta en titt på CAFxX sitt svar.

Det finnes ingen "magisk" måte å sjekke etter noe i et array uten en løkke. Selv om du bruker en funksjon, vil funksjonen selv bruke en løkke. Det du kan gjøre, er å bryte ut av løkken så snart du finner det du leter etter for å minimere beregningstiden.

var found = false;
for(var i = 0; i < vendors.length; i++) {
    if (vendors[i].Name == 'Magenic') {
        found = true;
        break;
    }
}

Svar #3

Ingen løkke nødvendig. Tre metoder som kommer i tankene:

Array.prototype.some()

Dette er det mest presise svaret på spørsmålet ditt, dvs. "sjekk om noe eksisterer", som antyder et boolsk resultat. Dette vil være sant hvis det finnes noen 'Magenic'-objekter, ellers usant:

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

Array.prototype.filter()

Dette vil returnere et array med alle 'Magenic'-objekter, selv om det bare er ett (vil returnere et array med ett element):

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

Hvis du prøver å tvinge dette til en boolean, vil det ikke fungere, siden en tom array (ingen 'Magenic'-objekter) fremdeles er sann. Så bruk bare magenicVendors.length i din betingelse.

Array.prototype.find()

Dette vil returnere det første 'Magenic'-objektet (eller undefined hvis det ikke finnes noen):

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

Dette tvinger til en boolean-verdi (ethvert objekt er sann, undefined er usann).


Merk: Jeg bruker vendor["Name"] i stedet for vendor.Name på grunn av den merkelige skrivemåten på egenskapsnavnene.

Merk 2: Ingen grunn til å bruke løs likhet (==) i stedet for streng likhet (===) når man sjekker navnet.

Svar #4

Det aksepterte svaret fungerer fortsatt, men nå har vi ECMAScript 6 innebygde metoder [Array.find][1] og [Array.some][2] for å oppnå samme effekt.

Array.some

Bruk some hvis du bare vil avgjøre om et element eksisterer, dvs. du trenger en true/false-avgjørelse.

Siterer MDN:

some()-metoden tester om minst ett element i arrayen består testen som er implementert av den oppgitte funksjonen. Den returnerer true hvis den i arrayen finner et element for hvilket den oppgitte funksjonen returnerer true; ellers returnerer den false. Den endrer ikke arrayen.

Array.find

Bruk find hvis du vil hente det samsvarende objektet fra arrayet, ellers returneres undefined.

Siterer MDN:

find()-metoden returnerer verdien av det første elementet i den oppgitte matrisen som oppfyller den oppgitte testfunksjonen. Hvis ingen verdier oppfyller testfunksjonen, returneres undefined.

let arr = [
  {
    id: 21,
    label: 'Banana',
  },
  {
    id: 22,
    label: 'Apple',
  }
]

/* note : data is the actual object that matched search criteria 
  or undefined if nothing matched */

let 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
}


/* note : doesExist is a boolean thats true or false depending on of whether the data was found or not */
let doesExist = arr.some(function(ele) {
    return ele.id === 21;
});


Se min jsfiddle-lenke. Det finnes en polyfill for IE levert av Mozilla.

Svar #5

Her er måten jeg ville gjort det på

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

array.some()-metoden sjekker om det finnes minst én verdi i et array som matcher kriteriene, og returnerer en boolean. Herfra kan du gå videre med:

if (found) {
// do something
} else {
// do something else
}

Svar #6

Med mindre du vil omstrukturere det slik:

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

som du kan gjøre if(vendors.Magnetic)

Du må løkke

Svar #7

Et JavaScript-array har to metoder, some og every metoder som returnerer en Boolean og kan hjelpe deg å oppnå dette.

Jeg tror some vil være mest passende for det du har til hensikt å oppnå.

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

Noen validerer at noen av objektene i arrayet oppfyller den gitte betingelsen.

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

every validerer at alle objektene i arrayen tilfredsstiller den gitte betingelsen.

Svar #8

I henhold til ECMAScript 6-spesifikasjonen kan du bruke findIndex.

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

magenicIndex vil holde enten 0 (som er indeksen i arrayet) eller -1 hvis det ikke ble funnet.

Svar #9

Siden OP har stilt spørsmålet om nøkkelen eksisterer eller ikke:

En mer elegant løsning som vil returnere en Boolean ved å bruke ES6 reduce-funksjonen kan være:

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

Merk: Den første parameteren til reduce er en false, og hvis arrayet har nøkkelen, vil det returnere true.

Svar #10

Du kan ikke uten å virkelig se på objektet.

Du burde sannsynligvis endre strukturen din litt, som

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

Da kan du bare bruke det som en oppslags-hash.

vendors['Microsoft']; // 'DEF'
vendors['Apple']; // undefined

Svar #11

const check = vendors.find((item)=>item.Name==='Magenic')

console.log(check)

Prøv denne koden.

Hvis elementet eller gjenstanden er til stede, vil utdataene vise deg det elementet. Hvis det ikke er til stede, vil utdataene være 'undefined'.

Svar #12

Testing for array elements:

JavaScript tilbyr array-funksjoner som lar deg oppnå dette relativt enkelt. De er følgende:

  1. Array.prototype.filter: Tar en callback-funksjon som er en test, arrayen blir deretter iterert over med denne callbacken og filtrert i henhold til den. Et nytt filtrert array returneres.
  2. Array.prototype.some: Tar en callback-funksjon som er en test, arrayen blir deretter iterert over med denne callbacken, og hvis noen elementer består testen, returneres sann (true). Ellers returneres usann (false)

Detaljene forklares best gjennom et eksempel:

Eksempel :

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');
}

Nettleserstøtte:

Disse 2 funksjonene er ES6-funksjoner, og ikke alle nettlesere støtter dem. For å omgå dette kan du bruke en polyfill. Her er polyfillen for Array.prototype.some (fra 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;
  };
}

Relaterte artikler