JavaScript'te bir nesne dizisinde bir değer nasıl bulunur?


91

Bir dizi nesnem var:

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

Anahtarın "akşam yemeği" olduğu nesneyi / diziyi arayabilmek ve "suşi" ile eşleşip eşleşmediğini görmek istiyorum.

JQuery'nin $ .inArray olduğunu biliyorum, ancak nesnelerin dizileri üzerinde çalışmıyor gibi görünüyor. Ya da belki yanılıyorum. indexOf ayrıca sadece bir dizi seviyesinde çalışıyor gibi görünüyor.

Bunun için bir işlev veya mevcut bir kod yok mu?


Bu daha önce sorulmuştu. Kendi işlevinizi yazmanız veya başka bir kitaplık kullanmanız gerekir.
Felix Kling

1
Lütfen ObjectJavascript'te ayrılmış olanın Objectnesne nesnesi, yani tüm nesnelerin anası olduğunu unutmayın.
adamse

1
soru ve kabul edilen yanıt, çok boyutlu dizilerle değil, öğelerinin özellik değerlerine göre 1 boyutlu dizi filtrelemesiyle ilgilidir. => "Çok boyutlu bir dizide bir değer bulma" sorunumu çözmediler.
Martin Schneider

Yanıtlar:


213

Gibi bir diziniz varsa

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

filterBir Array nesnesinin yöntemini kullanabilirsiniz :

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

Daha yeni JavaScript uygulamalarında bir işlev ifadesi kullanabilirsiniz:

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

"dinner": "sushi"Kullanan kişileri arayabilirsiniz.map

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

veya a reduce

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

Eminim bunu keyfi anahtarlara ve değerlere genelleyebilirsiniz!


7
Bu çözümlerin ECMAScript 5'in bir parçası olduğunu ve IE8'de desteklenmediğini unutmayın. kangax.github.com/es5-compat-table @ adamse'nin cevabını tercih etsem de, alex's daha "eski boktan tarayıcı" dostudur. Yine de performans konusunda emin değilim.
EasyCo

@SalmanA - ne de soru veya çözüm jQuery'ye atıfta bulunmuyor. Javascript filtresi () kullanılır, jQuery'ye özgü $ .filter () - tutorialspoint.com/javascript/array_filter.htm
Tapirboy

EasyCo'da belirtildiği gibi, filtre işlevi IE8'de desteklenmemektedir. Ancak, Array prototipine kolayca eklenir ve bu nedenle komut dosyalarınızın başında küçük bir işlevle herhangi bir tarayıcıda kullanılabilir. Bu, filtre belgelerinde özetlenmiştir . ECMA-262'de belirtilen tam işlevi verir, bu nedenle tam anlamıyla aynı şeydir.
dallin

1
JQuery'nin yöntemini kullanan bir yanıt ekledim grep. Yaptığınız şeyle aynı konsept olarak cevabınızı almak mantıklı olabilir, ancak jQuery bağımlı ve boktan tarayıcı dostu.
Zach Lysobey

Dönüş değişkenimle sürekli bir referans hatası almamın bir nedeni var mı? "X" i döndüren en iyi iki yanıtı denedim ve bunun tanımsız olduğunu söyleyip duruyor ...
Evan Lalo

18

jQuery, @ adamse'nin CevabındanjQuery.grep ES5 filterişlevine benzer şekilde çalışan ve eski tarayıcılarda iyi çalışması gereken yerleşik bir yönteme sahiptir .

Adamse örneğini kullanarak:

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

aşağıdakileri yapabilirsin

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

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 .

-1Hiç geçerli bir anahtar olmadığı sürece .


neredeyse bunu olumlu oyladı, ancak gönderide herhangi bir açıklama yoktu.
mickmackusa

10

Bu aramayı sık sık yapacaksanız, nesnenizin formatını değiştirmeyi düşünün, böylece akşam yemeği aslında bir anahtar olacaktır. Bu, bir veritabanı tablosunda birincil kümelenmiş bir anahtar atamaya benzer. Yani mesela:

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

Artık buna şu şekilde kolayca erişebilirsiniz: Object['sushi']['name']

Veya nesne gerçekten bu kadar basitse (nesnede yalnızca 'ad'), onu şu şekilde değiştirebilirsiniz:

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

Sonra gibi erişebilir: Object['sushi'].

Veri nesnenizi bu şekilde yeniden yapılandırmak her zaman mümkün değildir veya sizin yararınıza değildir, ancak önemli olan, bazen en iyi yanıt, veri nesnenizin en iyi şekilde yapılandırılıp yapılandırılmadığını düşünmektir. Bunun gibi bir anahtar oluşturmak daha hızlı olabilir ve daha temiz kodlar oluşturabilir.


1
Cevabınızı seviyorum, ancak sözdizimiyle ilgili bir sorun buldum: benimki yalnızca şu şekilde çalıştı: obj = {"pizza": {"name": "bob"}, "sushi": {"name": "john"}} alert ( obj ['pizza'] ['ad']); ama hala. Teşekkürler! aradığımı buldum! )
aleXela

@alexela Teşekkürler alexela! Cevabımı zeki gözleminizle güncelledim! Örneği OP'nin gönderisine kopyalamıştım ve alıntıları eklemeyi ihmal ettim, ama haklısın - en azından değerlerin etrafında alıntılar olmadığı sürece işe yaramayacak (değişkenler değil değerler olduğunu varsayarak).
dallin

3

Alasql kütüphanesi ile dizideki nesneyi bulabilirsiniz :

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

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

Bu örneği jsFiddle'da deneyin .


3
Bunun gerçekten olumsuz oylanmayı hak ettiğinden emin değilim. Koleksiyonlardaki SQL benzeri sorgular, gereksinimler tek bir filtreden daha karmaşık hale geldiğinde veya çağrıyı azalttığında, mantık yürütmek ve yazmak çok daha kolay hale gelir. Alasql oldukça etkileyici bir kütüphane, ancak kuşkusuz yukarıdaki örnek için biraz fazla.
TomDotTom

1
nesnenin kendisi bir SQL kaynağından geliyorsa, bu cevap saf dahidir.
edwardsmarkf

1

Basit bir in döngüsü kullanabilirsiniz:

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

Aşağıdaki keman örneği, içeren tüm nesneleri dinner:sushibir diziye koyar :

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


1

Burada zaten birçok iyi cevap var, bu yüzden neden bir tane daha, lodash veya alt çizgi gibi bir kitaplık kullanmayalım :)

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

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

0

Belirli bir yolu örten ilk yaprak öğesi için iç içe geçmiş bir site haritası yapısını aramak zorunda kaldım. Sadece .map() .filter()ve kullanarak aşağıdaki kodu buldum .reduce. Yolla eşleşen bulunan son öğeyi döndürür /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);

Düzenle 4n4904z07


0

Arama işlevi ile belirli bir nesneyi bulmak istiyorsanız, sadece şuna benzer bir şey deneyin:

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

Bu örnek bir nesnedir:

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

Kod yinelenecek ve "kullanıcı" dizisini bulacak ve içinde aradığınız nesneyi arayacaktır.

Benim sorunum, dizi dizininin her pencere yenilemesini değiştirmesi ve 3. veya ikinci dizide olmasıydı, ancak önemli değil.

Benim için bir cazibe gibi çalıştı!

Örneğinizde biraz daha kısadır:

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

0

Tekerleği yeniden icat etmemeye çalışırdım. Tüm veri işleme ihtiyaçlarımız için nesne taraması kullanıyoruz . Kavramsal olarak çok basit, ancak birçok harika şeye izin veriyor. İşte özel sorunuzu nasıl çözeceğiniz

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

const findDinner = (dinner, data) => objectScan(['*'], {
  abort: true,
  rtn: 'value',
  filterFn: ({ value }) => value.dinner === dinner
})(data);

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

console.log(findDinner('sushi', data));
// => { name: 'john', dinner: 'sushi' }
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.