Javascript dizisinin belirli bir değere eşit bir özniteliğe sahip bir nesne içerip içermediği nasıl belirlenir?


658

Benim gibi bir dizim var

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

Magenen'in var olup olmadığını görmek için bu diziyi nasıl kontrol edebilirim? Dönmem gerekmedikçe döngü istemiyorum. Potansiyel olarak birkaç bin kayıtla çalışıyorum.


GÜNCELLENMİŞ

Bu popüler bir gönderi olduğu için bulduğum yeni bir şeyi paylaşacağımı düşündüm. Ve @CAFxX bunu zaten paylaşmış görünüyor! Bunları daha sık okumalıyım. Ben rastladım https://benfrain.com/understanding-native-javascript-array-methods/ .

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

ECMAScript 2015 ile yeni ok işlevlerini kullanmak daha da kolay:

vendors.filter(vendor => vendor.Name === "Magenic")

Lütfen rastgele görünen yorumu affedin, ancak sorunuz JSON veya yalnızca JavaScript dizileriyle mi ilgili?
Alex Turpin

4
@CAFxX çözümü daha iyidir, seçilen çözümü güncellerseniz harika olur.
eMarine

1
Kabul etti, daha önce görmedim!
David Lozzi

Ok işlevlerini kullanarak bunu şimdi daha da basitleştirebilirsiniz. Tüm modern tarayıcılar bunu destekler ve daha hoş görünür.
Piotr Kula

harita işlevini kullanabilirsiniz, çok yararlı
Monir alhussini

Yanıtlar:


264

2018 edit : Bu cevap, tarayıcılar dizi filtreleme yöntemlerini ve ok işlevlerini geniş ölçüde desteklemeden önce 2011'den alınmıştır. CAFxX'in cevabına bir göz atın .

Bir dizide döngü olmayan bir şeyi kontrol etmenin "sihirli" yolu yoktur. Bazı işlevleri kullansanız bile, işlevin kendisi bir döngü kullanır. Yapabileceğiniz şey, hesaplama süresini en aza indirmek için aradığınızı bulduğunuzda döngüden çıkmaktır.

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

4
Sorun değil. Unutmayın Keith'in çözümü de çok canlı olduğunu ve döngü gelen kaydeder.
Alex Turpin

2
Bilmeniz gereken tek şey "bir şey" in bulunup bulunmadığı ise bir bayrağa ihtiyacınız yoktur, tarama dizininin değerini dizi boyutuyla kontrol edebilirsiniz. Bunun işe yaraması için indeks değişkeninin elbette for ifadesinden önce bildirilmesi gerekir.
Alex

5
Şu seçenekler çalışıyor gibi görünüyor: vendors.forEach, vendors.filter, vendors.reduce
David Lozzi

1
JSON.stringify (satıcılar) .indexOf ('Magenic')! == -1
Son Nefes

1
Eğer oldukça kolay bir Yanlış pozitiften neden olabilir @LastBreath 'Magenic'nesne başka bir yerde olduğunu
Alex Turpin

947

Yeniden keşfetmeye gerek yok tekerlekdöngü, en azından açıkça değil ( ok işlevlerini kullanarak , yalnızca modern tarayıcılar ):

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

veya daha iyisi :

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

EDIT: Berbat tarayıcılar ile uyumluluk gerekiyorsa, o zaman en iyi bahis:

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

4
@Rocket cevabımı neden düzenlediniz? Kıvırcık parantezleri olmayan sözdizimi mükemmel şekilde geçerli bir javascripttir .
CAFxX

4
"Lambda" sözdizimi Chrome 16'da hala çalışmıyor (ki bu çok kötü bir tarayıcı değil).
Rocket Hazmat

27
Bu berbat tanımınıza bağlı, sanırım. Bu sözdizimi javascript 1.8'in bir parçasıdır.
CAFxX

7
İfadesi kapanışları Eğer birinci ve ikinci örneklerde burada kullandığınız bir var kullanmayın, sigara içmek standardını! Mozilla'dan uyarı (bu bağlantıya bakın). Sadece Firefox'ta çalıştılar ve şimdi kullanımdan kaldırıldı ve ok işlevleri lehine kaldırılacaklar .
doppelgreener

2
@ 7hibault çünkü somebir nesne bulunduğunda kısa devre yapabilir name === "Magenic". İle filter, dizinin sonuna kadar her öğeyi kontrol eder ve koşulla eşleşen yeni bir dizi öğesi oluşturur, ardındanlength
adiga

93

Döngü gerekmez. Akla gelen üç yöntem:

Array.prototype.some ()

Bu, sorunuzun en kesin yanıtıdır, yani "bir şeyin olup olmadığını kontrol edin", bool sonucunu ima eder. Herhangi bir 'Magenik' nesne varsa bu doğrudur, aksi halde yanlış:

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

Array.prototype.filter ()

Bu, yalnızca bir tane olsa bile (tek öğeli bir dizi döndürür) tüm 'Magenic' nesnelerin bir dizisini döndürür:

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

Bunu bir boole'ye zorlamaya çalışırsanız, boş bir dizi ('Magenic' nesne yok) hala doğrudur. Bu yüzden sadece magenicVendors.lengthşartlı kullan.

) (Array.prototype.find

Bu, ilk 'Magenic' nesnesini döndürür (veya undefinedyoksa):

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

Bu bir boolean tamamına zorlar (herhangi bir nesne doğrudur, undefinedsahidir).


Not: Özellik adlarının garip gövdesi nedeniyle vendor.Name yerine vendor ["Name"] kullanıyorum.

Not 2: Adı kontrol ederken katı eşitlik (===) yerine gevşek eşitlik (==) kullanmak için hiçbir neden yoktur.


5
Kaputun altında bunların hepsinin ilmeklediğini belirtmek yararlıdır. Bunların hepsi basitçe döngü ve işlem yapmaktan ziyade hesaplama açısından daha yavaştır.
ThePartyTurtle

Bu sevgiyi burada da paylaşabilirsiniz: stackoverflow.com/questions/21748670/… bu yüzden benim gibi daha fazla kişi bu eski sayfaya gitmez ve varsayımlar yapmaz.
ThePartyTurtle

43

Kabul edilen cevap hala işe yarıyor, ancak şimdi [Array.find][1]aynı etkiyi elde etmek için ECMAScript 6 yerel yöntemimiz var .

MDN'den alıntı:

Find () yöntemi, dizideki sağlanan test işlevini karşılayan ilk öğenin değerini döndürür. Aksi takdirde undefined döndürülür.

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
}

Benim jsfiddle bağlantı görmek IE için Mozilla tarafından sağlanan bir çoklu dolgu var


2
Sadece yaparsanız daha kısa olabilir return ele.id == '2', ancak iyi bir ES6 çözümü için +1 olabilir.
Lye Fish

Yeni bir cevap almak güzel :) Performansın yukarıdaki cevaplardan daha iyi olup olmadığını merak etmek ...
Emidomenge

'Data' dönüş değerinin (ele.id '21' gibi bir id ile eşleştiğinde) dizi öğesinin kendisi (bu durumda, tüm öğe nesnesi) olacağını belirtmek önemlidir. Beklenti veri değişkeni sonucunun yanlış bir değer yerine 'doğru' veya 'yanlış' olması olsaydı, hayal kırıklığına uğrarsınız.
adamgede

Teşekkür! Görevim biraz farklıydı. Array içinde Object dizinini al => push if <0 || splice(index, 1)İşte biraz güncellenmiş kod:const index = this.selected.indexOf(this.selected.find(s => s.id == passedObj.id))
Leonid Zadorozhnykh

30

İşte yapmamın yolu

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

array.some()yöntemi, bir dizide ölçütlerle eşleşen ve bir boole döndüren en az bir değer olup olmadığını denetler. Buradan şuraya gidebilirsiniz:

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

22

Bu şekilde yeniden yapılandırmak istemiyorsanız:

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

yapabileceğiniz if(vendors.Magnetic)

Dönmeniz gerekecek


2
Halen başka yerde kullanmak için nesne yapısını korumak istediğinde
Keith.Abramo

21

ECMAScript 6 spesifikasyonuna göre kullanabilirsiniz findIndex.

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

magenicIndex0(dizideki dizin) ya -1da bulunamazsa tutacaktır .


Sadece insanları koşul olarak kullanıldıysa 0'ın yanlış bir sonuç olarak eşleşeceğini bilmelerini sağlamak için. Bu nedenle daha mantıklı bir doğruluk değerlendirmesi alırken find () yönteminin daha iyi olduğunu düşünüyorum .
dhj

15

OP'nin anahtarın var olup olmadığını sorusunu sorduğu gibi .

ES6 azaltma işlevi kullanılarak boole döndürecek daha zarif bir çözüm olabilir

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

Not: reduce'nın ilk parametresi a'dır falseve dizinin anahtarı varsa true değerini döndürür.

Umarım daha iyi ve daha temiz kod uygulaması için yardımcı olur


1
Ne zamandan beri !! [] yanlış'a eşittir?
Sergey

1
Güzel yakalayış.
Jay Chakra

1
Bu yanlış. İlk parametre nesne reducedeğil akümülatördür vendor. Bu false.Name === "Magenic"her döngüyü kontrol eder ve yanlış döndürür
adiga

@adiga: Düzeltildi.
Jay Chakra

1
Lütfen Mirza Leka'nın çözümünü de kontrol edin. Çok daha zarif bir çözüm.
Jay Chakra

13

Nesneye gerçekten bakmadan yapamazsınız.

Muhtemelen yapınızı biraz değiştirmelisiniz,

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

Sonra sadece bir arama karması gibi kullanabilirsiniz.

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

6

Çok geç olabilir, ancak javascript dizisinde bir boole döndüren ve bunu başarmanıza yardımcı olabilecek iki yöntem someve everyyöntem vardır.

Bence somebaşarmayı düşündüğünüz şeyler için en uygun olur.

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

Bazıları dizideki nesnelerin herhangi birinin belirtilen koşulu karşıladığını doğrular.

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

Her biri dizideki tüm nesnelerin belirtilen koşulu karşıladığını doğrular.


İşe yaramaz, const array1 = [{name:'Mike'},{name:'Alice'}]; console.log(array1.every(item => item.name !== 'Mike'));gerçek
dönmelidir

Üzgünüm dostum, somecevabımı güncelleyecektim.
Akinjiola Toni

5

Dönmek zorundasın, etrafında bir yol yok.

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];
    }
  }
}

Elbette bunu daha hoş hale getirmek için linq.js gibi bir kütüphane kullanabilirsiniz :

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

( demo için bkz. jsFiddle )

Linq.js'nin düz bir döngüden daha hızlı olacağından şüpheliyim, ancak işler biraz daha karmaşık olduğunda kesinlikle daha esnektir.


5

Dizi elemanları testi:

JS, bunu nispeten kolay bir şekilde gerçekleştirmenizi sağlayan dizi işlevleri sunar. Bunlar:

  1. Array.prototype.filter: Bir test olan bir geri çağırma işlevi alır, daha sonra dizi geri çağrılarak tekrarlanır ve bu geri çağrıya göre filtrelenir. Yeni filtre uygulanmış bir dizi döndürülür.
  2. Array.prototype.some: Bir sınama işlevi olan bir geri çağırma işlevi alır, sonra dizi ile geri çağrılır ve geri çağırma olur ve herhangi bir öğe sınamayı geçerse , boolean true döndürülür. Aksi takdirde yanlış döndürülür

Özellikler en iyi şekilde bir örnekle açıklanmaktadır:

Misal:

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

Tarayıcı desteği:

Bu 2 işlev ES6işlevdir, tüm tarayıcılar bunları desteklemeyebilir. Bunun üstesinden gelmek için bir çoklu dolgu kullanabilirsiniz. İşte Array.prototype.some( MDN'den) için çoklu dolgu :

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


4

jquery kullanıyorsanız, eşleşen tüm nesnelerle dizi oluşturmak için grep'ten yararlanabilirsiniz:

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

ve sonra sonuç dizisini kullanın:

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

3

Eğer yanılıyorsam beni düzeltin .. forEachböyle bir yöntem kullanabilirdim,

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

   }
});

Günümüzde, basitlik ve açıklayıcı kelime nedeniyle alışkınım. Teşekkür ederim.


1
Not: Buraya dönüşün faydası yok
Edison

2

Benim için bu işi deneyebilirsiniz.

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

Bu gerçekten eski bir soru ve bence güncellemesi bugünlerde en iyi çözüme sahip.
Federico Galfione

1

Lodash kullanabilirsiniz . Lodash kütüphanesi uygulamanız için çok ağırsa, kullanılmayan gereksiz fonksiyonu kapatmayı düşünün.

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

Bunu yapmanın sadece bir yolu. Bir diğeri olabilir:

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

console.log(arr);

Yukarıdaki örnek, aşağıdaki gibi bir kitaplık kullanılmadan da yeniden yazılabilir :

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

Umarım cevabım yardımcı olur.


1

Burada birçok cevap iyi ve oldukça kolaydır. Ancak nesne diziniz sabit bir değer kümesine sahipse, aşağıdaki hileyi kullanabilirsiniz:

Bir nesnedeki tüm adı eşleyin.

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

Şimdi bu dirtyObj herhangi bir döngü olmadan tekrar tekrar kullanabilirsiniz.

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

1

Bir nesneyi diğeriyle karşılaştırmak için, bir for in döngüsü (nesneler arasında döngü yapmak için kullanılır) ve some () birleştiririm. Bazı kodları kaydederek sınırların dışına çıkma gibi bir dizi hakkında endişelenmenize gerek yoktur. .Some ile ilgili dokümanları burada bulabilirsiniz

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

Bir nesneyi diğeriyle karşılaştırmanın alternatif bir yolu, dizideki nesnelerin miktarını elde etmek için iç içe bir döngü Object.keys (). Uzunluğu ile kullanmaktır. Aşağıdaki kod:

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

Sorunuzu tam olarak cevaplamak için, yalnızca bir nesnede bir değer arıyorsanız, döngü içinde bir tane kullanabilirsiniz.

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

0

Alternatif olarak şunları yapabilirsiniz:

const find = (key, needle) => return !!~vendors.findIndex(v => (v[key] === needle));

1
neden bunu yapabileceğini söylesen iyi olur
Azzabi Haythem

0

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

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

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


Bence sonuç demek istedin Sonuç: [{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) {
   ...
}

3
Lütfen ve bazı açıklamalar sağlayın ve sağladığınız örneğin çalıştığından emin olun .. (filtre orijinal diziyi değiştirmez ancak klonlar).
Moshe Simantov

-1

Bu sorunu çözme yaklaşımım, ES6'yı kullanmak ve bizi kontrol eden bir işlev oluşturmaktır. Bu fonksiyonun yararı proje verilen nesnelerin herhangi dizisini kontrol etmek için dışarı aracılığıyla o yeniden olabilmesidir keyve valuekontrol etmek.

YETERLİ KONUŞMAK, KODU GÖRMEK İSTİYORUM

Dizi

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

fonksiyon

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

Çağrı / Kullanım

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

const found = arrayIncludesInObj(ceos, "name", "Tim Bezos"); // false

-4

Regex ile gitmek istiyorum.

Kodunuz aşağıdaki gibi ise,

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

Ben tavsiye ederim

/"Name":"Magenic"/.test(JSON.stringify(vendors))

23
Bazı insanlar bir sorunla karşılaştıklarında "Biliyorum, düzenli ifadeler kullanacağım" diye düşünüyorlar. Şimdi onların iki problemi var.
Craicerjack

Bunu bir şey yapabileceğiniz için altında dosyalamanız gerektiği anlamına gelmez.
Liam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.