Bagaimana menemukan nilai dalam array objek di JavaScript?

91

Saya memiliki array objek:

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

Saya ingin dapat mencari objek / larik di mana kuncinya adalah "makan malam", dan melihat apakah cocok dengan "sushi".

Saya tahu jQuery memiliki $ .inArray, tetapi tampaknya tidak berfungsi pada array objek. Atau mungkin saya salah. indexOf juga tampaknya hanya bekerja pada satu level array.

Apakah tidak ada fungsi atau kode untuk ini?

Penanya
sumber
Ini telah ditanyakan sebelumnya. Anda harus menulis fungsi Anda sendiri atau menggunakan perpustakaan lain.
Felix Kling
1
Harap dicatat bahwa Objectyang dicadangkan dalam Javascript, Objectadalah objek objek, yaitu ibu dari semua objek.
adamse
1
pertanyaan dan jawaban yang diterima tidak terkait dengan array multidimensi tetapi lebih ke pemfilteran array 1 dimensi berdasarkan nilai properti itemnya. => Mereka tidak memecahkan masalah saya "menemukan nilai dalam array multidimensi".
Martin Schneider

Jawaban:

213

Jika Anda memiliki array seperti

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

Anda dapat menggunakan filtermetode objek Array:

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

Dalam implementasi JavaScript yang lebih baru, Anda dapat menggunakan ekspresi fungsi:

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

Anda dapat mencari orang yang telah "dinner": "sushi"menggunakan filemap

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

atau a reduce

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

Saya yakin Anda dapat menggeneralisasi ini ke kunci dan nilai arbitrer!

adamse
sumber
7
Perlu diingat bahwa solusi ini adalah bagian dari ECMAScript 5 dan tidak didukung di IE8. kangax.github.com/es5-compat-table Sebanyak saya lebih suka jawaban @ adamse, alex lebih ramah "browser lama yang menyebalkan". Tidak yakin dengan kinerjanya.
EasyCo
@SalmanA - atau pertanyaan atau solusinya tidak mengacu pada jQuery. Filter javascript () digunakan, bukan khusus jQuery $ .filter () - tutorialspoint.com/javascript/array_filter.htm
Tapirboy
Seperti yang disebutkan oleh EasyCo, fungsi filter tidak didukung di IE8. Namun, ini dengan mudah ditambahkan ke prototipe Array dan dengan demikian dapat digunakan di browser apa pun dengan fungsi kecil di awal skrip Anda. Ini diuraikan dalam dokumentasi filter . Ini memberikan fungsi yang persis seperti yang ditentukan dalam ECMA-262, jadi secara harfiah hal yang sama.
dallin
1
Saya baru saja menambahkan jawaban yang menggunakan grepmetode jQuery . Mungkin masuk akal untuk memasukkan jawaban Anda karena konsepnya sama dengan apa yang Anda lakukan, tetapi bergantung pada jQuery dan ramah browser yang menyebalkan.
Zach Lysobey
Apakah ada alasan mengapa saya terus mendapatkan kesalahan referensi dengan variabel pengembalian saya? Saya mencoba dua jawaban teratas yang mengembalikan "x '' dan terus mengatakan itu tidak ditentukan ...
Evan Lalo
18

jQuery memiliki metode bawaanjQuery.grep yang bekerja mirip dengan filterfungsi ES5 dari Answer @ adamse dan seharusnya berfungsi dengan baik di browser lama.

Menggunakan contoh adamse:

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

Anda dapat melakukan hal berikut

jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]
Zach Lysobey
sumber
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 .

Selama -1tidak pernah ada kunci yang valid.

alex
sumber
hampir memilih yang ini, tetapi tidak ada penjelasan di pos.
mickmackusa
10

Jika Anda akan sering melakukan pencarian ini, pertimbangkan untuk mengubah format objek Anda sehingga makan malam adalah kuncinya. Ini seperti menetapkan kunci berkerumun utama dalam tabel database. Jadi, misalnya:

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

Sekarang Anda dapat dengan mudah mengaksesnya seperti ini: Object['sushi']['name']

Atau jika objeknya benar-benar sesederhana ini (hanya 'nama' di objek), Anda bisa mengubahnya menjadi:

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

Dan kemudian mengaksesnya seperti: Object['sushi'].

Jelas tidak selalu mungkin atau menguntungkan Anda untuk merestrukturisasi objek data seperti ini, tetapi intinya adalah, terkadang jawaban terbaik adalah mempertimbangkan apakah objek data Anda terstruktur dengan cara terbaik. Membuat kunci seperti ini bisa lebih cepat dan membuat kode lebih bersih.

dallin
sumber
1
Senang Anda menjawab, tetapi saya menemukan masalah dengan sintaks: milik saya hanya bekerja seperti ini: obj = {"pizza": {"name": "bob"}, "sushi": {"name": "john"}} peringatan ( obj ['pizza'] ['nama']); tetapi tetap saja. Terima kasih! menemukan apa yang saya cari! )
aleXela
@alexela Terima kasih alexela! Saya memperbarui jawaban saya dengan pengamatan cerdik Anda! Saya baru saja menyalin contoh di posting OP dan mengabaikan untuk menambahkan tanda kutip, tetapi Anda benar - itu tidak akan berfungsi kecuali ada tanda kutip setidaknya di sekitar nilai (dengan asumsi itu adalah nilai dan bukan variabel).
dallin
3

Anda dapat menemukan objek dalam array dengan perpustakaan Alasql :

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

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

Coba contoh ini di jsFiddle .

agershun
sumber
3
Saya tidak yakin ini benar-benar pantas untuk ditolak. Kueri seperti Sql pada koleksi menjadi jauh lebih mudah untuk bernalar dan ditulis ketika persyaratan menjadi lebih rumit daripada satu filter atau kurangi panggilan. Alasql adalah perpustakaan yang cukup mengesankan, tetapi memang agak berlebihan untuk contoh di atas.
TomDotTom
1
jika objek itu sendiri berasal dari sumber SQL, maka jawaban ini benar-benar jenius.
edwardsmarkf
1

Anda dapat menggunakan for in loop:

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

Contoh biola berikut menempatkan semua objek yang berisi dinner:sushike dalam sebuah array:

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

Rotareti
sumber
1

Sudah ada banyak jawaban bagus di sini jadi mengapa tidak satu lagi, gunakan perpustakaan seperti lodash atau garis bawah :)

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
sumber
0

Saya harus mencari struktur peta situs bersarang untuk item daun pertama yang menghasilkan jalur tertentu. Saya datang dengan kode berikut hanya menggunakan .map() .filter()dan .reduce. Mengembalikan item terakhir yang ditemukan yang cocok dengan jalur /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);

Edit 4n4904z07

Marc
sumber
0

Jika Anda ingin mencari objek tertentu melalui fungsi pencarian coba saja seperti ini:

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

Ini adalah contoh objek:

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

Kode akan mengulangi dan menemukan array "pengguna" dan akan mencari objek yang Anda cari di dalamnya.

Masalah saya adalah ketika indeks array berubah setiap refresh jendela dan itu baik di array ke-3 atau kedua, tetapi itu tidak masalah.

Bekerja seperti pesona bagi saya!

Dalam contoh Anda, ini sedikit lebih pendek:

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
sumber
0

Saya akan mencoba untuk tidak menemukan kembali kemudi. Kami menggunakan pemindaian objek untuk semua kebutuhan pemrosesan data kami. Ini secara konseptual sangat sederhana, tetapi memungkinkan banyak hal keren. Inilah cara Anda menjawab pertanyaan spesifik Anda

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' }
Vincent
sumber