Temukan objek dengan id dalam array objek JavaScript

1547

Saya punya array:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

Saya tidak dapat mengubah struktur array. Saya sedang melewati id 45, dan saya ingin mendapatkan 'bar'objek dalam array.

Bagaimana saya melakukan ini dalam JavaScript atau menggunakan jQuery?

premanb
sumber

Jawaban:

1193

Gunakan find()metode:

myArray.find(x => x.id === '45').foo;

Dari MDN :

The find()Metode mengembalikan nilai pertama dalam array, jika elemen dalam memenuhi berbagai fungsi pengujian yang disediakan. Kalau undefinedtidak dikembalikan.


Jika Anda ingin menemukan indeksnya , gunakan findIndex():

myArray.findIndex(x => x.id === '45');

Dari MDN :

The findIndex()method mengembalikan indeks dari elemen pertama dalam array yang memenuhi disediakan pengujian fungsi. Kalau tidak -1 dikembalikan.


Jika Anda ingin mendapatkan array elemen yang cocok, gunakan filter()metode ini sebagai gantinya:

myArray.filter(x => x.id === '45');

Ini akan mengembalikan array objek. Jika Anda ingin mendapatkan array fooproperti, Anda bisa melakukan ini dengan map()metode:

myArray.filter(x => x.id === '45').map(x => x.foo);

Catatan samping: metode seperti find()atau filter(), dan fungsi panah tidak didukung oleh browser lama (seperti IE), jadi jika Anda ingin mendukung browser ini, Anda harus mengubah kode Anda menggunakan Babel (dengan polyfill ).

Michał Perłakowski
sumber
2
Oleh karena itu untuk beberapa kondisi pengujian, hal itu akan menjadi seperti: myArray.find (x => x.id === '45' && x.color == 'red'). Foo
Apqu
2
Bagi saya, jawaban terbaik sejauh ini. Tidak perlu jQuery dan tidak membuat array bantu baru.
Canta
myArray.find (x => x.id === '45') tidak berfungsi pada PC mac
Govinda Rajbhar
@ TJCrowder Saya tidak berpikir itu ide yang baik untuk menyalin dan menempelkan polyfill dari MDN ke dalam kode Anda; sebagai gantinya, Anda harus menggunakan paket npm dengan polyfill. Dan Babel tidak termasuk polyfill untuk fitur ES2015 +, dalam paket babel-polyfill .
Michał Perłakowski
2
myArray.find (x => x.id === '45'). foo; melempar pengecualian jika tidak ada objek dengan id '45'.
Frazer Kirkman
1466

Karena Anda sudah menggunakan jQuery, Anda bisa menggunakan fungsi grep yang dimaksudkan untuk mencari array:

var result = $.grep(myArray, function(e){ return e.id == id; });

Hasilnya adalah array dengan item yang ditemukan. Jika Anda tahu bahwa objek itu selalu ada dan itu hanya terjadi sekali, Anda bisa menggunakannyaresult[0].foo untuk mendapatkan nilainya. Kalau tidak, Anda harus memeriksa panjang array yang dihasilkan. Contoh:

if (result.length === 0) {
  // no result found
} else if (result.length === 1) {
  // property found, access the foo property using result[0].foo
} else {
  // multiple items found
}
Guffa
sumber
124
Akan lebih aman untuk digunakan ===daripada ==, untuk menghindari masalah aneh dengan ==operator JavaScript .
Vicky Chijwani
11
@VickyChijwani: Apakah ada masalah saat membandingkan string ke string?
Guffa
38
Nah, jika Anda benar - benar yakin bahwa keduanya e.iddan idakan menjadi string, saya kira tidak apa-apa untuk digunakan ==. Tapi jika Anda tidak yakin, Anda mungkin menghadapi masalah (karena '' == 0merupakan truetetapi '' === 0adalah false). Belum lagi ===tampaknya lebih cepat ( stackoverflow.com/questions/359494/… ).
Vicky Chijwani
101
Pada dasarnya saya selalu menggunakan ===karena berfungsi persis seperti ==di bahasa pemrograman lain. Saya menganggap ==tidak ada dalam JavaScript.
Vicky Chijwani
6
@de. Banyak jawaban di sini memberikan perilaku yang diinginkan ketika mencari nilai-nilai unik; Anda pada dasarnya dapat mengenali mereka dengan fakta bahwa mereka kembali atau memutus dari loop mereka lebih awal (atau menginstruksikan konstruk tingkat rendah untuk menghentikan iterasi). Lihat jawaban JaredPar untuk contoh kanonik, dan komentar Aaronius tentang jawaban itu untuk wawasan yang sama. Secara umum, orang membedakan antara fungsi "filter" dan "menemukan" dengan cara ini, tetapi terminologi bervariasi. Meskipun lebih efisien, ini masih merupakan pencarian linier, jadi jika Anda ingin menggunakan tabel hash, lihat jawaban Aaron Digulla (berhati-hatilah terhadap detail impl.).
mentega
362

Solusi lain adalah membuat objek pencarian:

var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
    lookup[array[i].id] = array[i];
}

... now you can use lookup[id]...

Ini sangat menarik jika Anda perlu melakukan banyak pencarian.

Ini tidak akan membutuhkan lebih banyak memori karena ID dan objek akan dibagikan.

Aaron Digulla
sumber
6
Persis apa yang saya cari. Lucu bagaimana saya mencoba terlalu rumit dengan mencoba untuk mengulang setiap kali, menghapus setiap item dari daftar ketika saya menemukannya ketika saya hanya perlu mengubah data yang diterima dari CouchDB dan memasukkannya ke dalam format yang berguna untuk saya kebutuhan. +1 pak!
Slickplaid
5
ini pintar. Saya tidak bisa membayangkan bagaimana orang lain diyakinkan dengan melihat seluruh array untuk setiap penggunaan.
Aladdin Mhemed
4
Selama Anda tidak bergantung pada urutan properti: stackoverflow.com/questions/4886314/…
Marle1
Menggunakan istirahat; dalam loop pilihan / peningkatan yang baik jika Anda tahu hanya ada satu objek untuk ditemukan?
irJvV
7
@irJvV: Tidak, itu sama sekali tidak masuk akal. Kode di atas berguna jika Anda perlu melakukan banyak pencarian. Jika Anda melihat sekali saja, maka membuat lookupobjek adalah buang-buang waktu.
Aaron Digulla
174

ECMAScript 2015 menyediakan metode find () pada array:

var myArray = [
 {id:1, name:"bob"},
 {id:2, name:"dan"},
 {id:3, name:"barb"},
]

// grab the Array item which matchs the id "2"
var item = myArray.find(item => item.id === 2);

// print
console.log(item.name);

Ini bekerja tanpa perpustakaan eksternal. Tetapi jika Anda ingin dukungan browser yang lebih lama, Anda mungkin ingin memasukkan polyfill ini .

Rúnar Berg
sumber
1
Mungkin menyebabkannya masih tampak sangat eksperimental dan tidak banyak browser mendukungnya, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
lejonl
2
Ini dapat disederhanakan menjadi myArray.find(d=>d.id===45).foo;.
Shaggy
1
@ Shaggy atau genap myArray.find(({ id }) => id === 45).foo. Tapi ini adalah jawaban lama yang ditulis sebelum sintaksis ES2015 juga didukung seperti sekarang. @ Gothdo menjawab saat ini yang paling baru di utas.
Rúnar Berg
1
@Shaggy jika .find () mengembalikan tidak terdefinisi, maka optimasi Anda membuat kesalahan. Jadi solusi ini hanya dapat digunakan dalam kasus di mana kecocokan dijamin.
Herbert Peters
1
@HerbertPeters Jika Anda ingin memastikan Anda dapat alway null-cek, yang akan benar-benar mudah dengan chaining opsional : myArray.find(d => d.id === 45)?.foo.
Rúnar Berg
141

Underscore.js memiliki metode yang bagus untuk itu:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })
GijsjanB
sumber
42
Sebagai catatan, Lo-Dash (yang seringkali jauh lebih performant daripada Underscore) memiliki metode yang sama. Documents di sini: lodash.com/docs#find
user456584
Jika Anda hanya mengharapkan satu objek, maka menggunakan findWhere akan lebih efisien karena setelah menemukan satu hasil, pencarian tidak akan melangkah lebih jauh.
Foreever
@Foreever Dari dokumen _.find: "Fungsi kembali segera setelah menemukan elemen yang dapat diterima, dan tidak melintasi seluruh daftar."
GijsjanB
129

Saya pikir cara termudah adalah sebagai berikut, tetapi itu tidak akan berfungsi di Internet Explorer 8 (atau sebelumnya):

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property
pimvdb
sumber
Saya penasaran, adakah keunggulan kinerja di sini dibandingkan dengan biasanya for?
Igor Zinov'yev
@Igor Zinov'yev: Ya, tentu ada dampak kinerja dengan alat array ES5 itu. Fungsi terpisah dijalankan untuk setiap elemen, sehingga tidak akan terlalu cepat dibandingkan dengan forloop langsung .
pimvdb
Jadi maksudmu lebih lambat? Juga, ia akan selalu memindai seluruh array, sejauh yang saya bisa lihat, sedangkan forloop akan berakhir pada pertandingan pertama.
Igor Zinov'yev
Jika Anda memerlukan dukungan untuk IE8, cukup taruh ini di: stackoverflow.com/questions/7153470/…
Adam Grant
Kode ini akan menimbulkan kesalahan jika tidak ada elemen dengan ituid
Stan
71

Coba yang berikut ini

function findById(source, id) {
  for (var i = 0; i < source.length; i++) {
    if (source[i].id === id) {
      return source[i];
    }
  }
  throw "Couldn't find object with id: " + id;
}
JaredPar
sumber
17
Ini tidak layak untuk jawabannya sendiri, tetapi di browser modern solusi ini dapat ditulis sebagai: jsfiddle.net/rwaldron/j3vST
Rick
12
Jika Anda ingin efisiensi, perhatikan bahwa contoh ini kemungkinan lebih cepat daripada menggunakan filter () (lihat contoh Rick) karena yang ini kembali setelah menemukan item yang cocok pertama sedangkan filter () terus berjalan melalui array penuh bahkan setelah menemukan pertandingan. Yang ini juga tidak memiliki biaya untuk membuat array tambahan atau memanggil fungsi untuk setiap item.
Aaronius
3
@Rick, hal yang paling menarik tentang jawaban itu rupanya Anda dapat menambahkan konsol pembakar ke jendela output di jsFiddle. Ini jauh lebih baik daripada masuk dan menyuruh orang lain untuk membuka konsol untuk melihat hasilnya. Luar biasa!
KyleMit
1
Karena belum ada yang menyebutkannya sejauh ini, saya ingin menambahkan bahwa AngularJS juga memiliki metode filter .
Eno
31

Versi generik dan lebih fleksibel dari fungsi findById di atas:

// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var result_obj = objectFindByKey(array, 'id', '45');
akan Farrell
sumber
15

Anda bisa mendapatkan ini dengan mudah menggunakan fungsi map () :

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var found = $.map(myArray, function(val) {
    return val.id == 45 ? val.foo : null;
});

//found[0] == "bar";

Contoh kerja: http://jsfiddle.net/hunter/Pxaua/

pemburu
sumber
1
Saya lupa tentang fakta bahwa jQuery mapsecara otomatis menghapus nullelemen. Kedengarannya menyesatkan bagi saya dan konsep umum map, karena hasilnya tidak sama dengan koleksi aslinya.
MaxArt
14

Anda dapat menggunakan filter,

  function getById(id, myArray) {
    return myArray.filter(function(obj) {
      if(obj.id == id) {
        return obj 
      }
    })[0]
  }

get_my_obj = getById(73, myArray);
Joe Lewis
sumber
1
@TobiasBeuving - Yang menggunakan Array.find () juga JS sederhana dan harus berhenti pada pencarian pertama sehingga akan lebih efisien.
Adrian Lynch
12

Walaupun ada banyak jawaban yang benar di sini, banyak dari mereka tidak membahas fakta bahwa ini adalah operasi yang tidak perlu mahal jika dilakukan lebih dari satu kali. Dalam kasus ekstrim ini bisa menjadi penyebab masalah kinerja nyata.

Di dunia nyata, jika Anda memproses banyak item dan kinerja menjadi masalah, awalnya lebih cepat untuk membangun pencarian:

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

Anda kemudian bisa mendapatkan item dalam waktu yang tetap seperti ini:

var bar = o[id];

Anda juga dapat mempertimbangkan menggunakan Peta alih-alih objek sebagai pencarian: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

Tom
sumber
11

Menggunakan asli Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

mengembalikan elemen objek jika ditemukan, jika tidak false

laggingreflex
sumber
Sekedar catatan, Array.reduce tidak didukung di IE8 dan di bawah.
Burn_E99
7

Jika Anda melakukan ini beberapa kali, Anda dapat mengatur Peta (ES6):

const map = new Map( myArray.map(el => [el.id, el]) );

Maka Anda cukup melakukan:

map.get(27).foo
Jonas Wilms
sumber
6

Inilah cara saya melakukannya dalam JavaScript murni, dengan cara paling minimal yang dapat saya pikirkan yang berfungsi di ECMAScript 3 atau lebih baru. Ia kembali segera setelah kecocokan ditemukan.

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'
Dan W
sumber
5

Lebih generik dan pendek

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

dalam kasus Anda Kel. var element = findFromArray(myArray,'id',45)itu akan memberi Anda seluruh elemen.

Savan Kaneriya
sumber
4

Anda dapat mencoba Sugarjs dari http://sugarjs.com/ .

Ini memiliki metode yang sangat manis pada Array .find,. Jadi Anda dapat menemukan elemen seperti ini:

array.find( {id: 75} );

Anda juga dapat meneruskan objek dengan properti lebih banyak untuk menambahkan "di mana-klausa" lainnya.

Perhatikan bahwa Sugarjs memperluas objek asli, dan beberapa orang menganggap ini sangat jahat ...

deepflame
sumber
2
Yah, itu adalah jahat, karena dapat terjadi bahwa versi EcmaScript baru dapat memperkenalkan metode baru dengan nama yang sama. Dan coba tebak, inilah tepatnya yang terjadi denganfind . Saran saya adalah jika Anda ingin memperluas prototipe asli, selalu gunakan nama yang lebih spesifik, biarkan yang paling sederhana untuk pengembangan standar di masa depan.
MaxArt
komentar ini hampir 2 tahun dan hari ini saya lebih suka menggunakan lodash. Namun jika mau, Anda dapat membaca tentang topik ini di situs web sugarjs. Mereka mengambil sikap yang baik menurut pendapat Anda: sugarjs.com/native
deepflame
1
Operasi itu memang secara khusus meminta solusi javascript atau jquery
Tobias Beuving
4

Membangun jawaban yang diterima:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

Atau CoffeeScript:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo
stevenspiel
sumber
4

Baru-baru ini, saya harus menghadapi hal yang sama di mana saya perlu mencari string dari array yang sangat besar.

Setelah beberapa pencarian saya menemukan itu akan mudah ditangani dengan kode sederhana:

Kode:

var items = mydata.filter(function(item){
    return item.word.toLowerCase().startsWith( 'gk );
})

Lihat https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/

Serach dari string 20k

maheshwaghmare
sumber
3

Iterasi item apa pun dalam array. Untuk setiap item yang Anda kunjungi, periksa id item itu. Jika itu cocok, kembalikan.

Jika Anda hanya ingin kode:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

Dan hal yang sama menggunakan metode Array ECMAScript 5:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}
Zirak
sumber
3

Selama browser mendukung ECMA-262 , edisi ke-5 (Desember 2009), ini akan berfungsi, hampir satu baris:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});
agaton
sumber
2
Hampir. bFoundhanyalah sebuah boolean yang truejika suatu elemen memenuhi kondisi yang diperlukan.
MaxArt
3

Anda dapat melakukan ini bahkan dalam JavaScript murni dengan menggunakan fungsi "filter" bawaan untuk array:

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}

Jadi sekarang cukup berikan "id" di tempat keydan "45" di tempat value, dan Anda akan mendapatkan objek penuh yang cocok dengan id 45. Jadi,

myArr.filterObjects("id", "45");
kaizer1v
sumber
16
Jangan memodifikasi objek yang bukan milik Anda.
Michał Perłakowski
3

Gunakan Array.prototype.filter()fungsi.

DEMO : https://jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON

var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];

SARING

var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}
Sumit Ridhal
sumber
bagaimana cara mencari di dalam objek bersarang? Seperti hewan peliharaan = palsu harus mengembalikan dua objek.
Berlaku
gunakan .filtermetode di obj.infodalam nested loop. var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
Sumit Ridhal
Anda dapat menggunakan gaya es6 juga imo ... const filterData = jsonObj.filter (obj => obj.name === 'Alex')
DagicCross
3

Kita bisa menggunakan metode Jquery $.each()/$.grep()

var data= [];
$.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}

atau

var data = $.grep(array, function( n, i ) {
  return ( n !== 5 && i > 4 );
});

gunakan sintaks ES6:

Array.find, Array.filter, Array.forEach, Array.map

Atau gunakan Lodash https://lodash.com/docs/4.17.10#filter , Underscore https://underscorejs.org/#filter

TLbiz
sumber
2

Saya benar-benar menyukai jawaban yang diberikan oleh Aaron Digulla tetapi perlu menyimpan berbagai objek saya sehingga saya bisa mengulanginya nanti. Jadi saya memodifikasinya

	var indexer = {};
	for (var i = 0; i < array.length; i++) {
	    indexer[array[i].id] = parseInt(i);
	}
	
	//Then you can access object properties in your array using 
	array[indexer[id]].property

quincyaft
sumber
Menggunakan solusi yang sama dengan tercepat untuk menemukan item dalam array. Tapi parseInt berlebihan di sini.
aleha
1

Menggunakan:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

Seharusnya mengembalikan objek dengan id.

volumexxx
sumber
Anda dapat mempersingkat kode Anda dengan menggunakan return obj.id === 5? obj: false; Saya menggunakan $. Masing-masing untuk iterasi pada array.
marcel
@marcel: Itu tidak akan berhasil. Sebagai return false akan mengakhiri loop, itu hanya akan menemukan objek jika item pertama dalam array.
Guffa
1

Solusi ini dapat membantu juga:

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

Saya membuatnya seperti $.grepdan jika satu objek mengetahui, fungsi akan mengembalikan objek, bukan array.

soytian
sumber
2
Jangan memodifikasi objek yang bukan milik Anda.
Michał Perłakowski
@ Gotdo I Agree. Jika seseorang tidak tahu function will return the object, rather than an arraybisa mendapatkan kesalahan, tapi saya pikir itu tergantung pada pengguna.
soytian
0

Mulai dari jawaban aggaton , ini adalah fungsi yang benar-benar mengembalikan elemen yang diinginkan (atau nulljika tidak ditemukan), mengingat arraydan callbackfungsi yang mengembalikan nilai kebenaran untuk elemen "benar":

function findElement(array, callback) {
    var elem;
    return array.some(function(e) {
        if (callback(e)) {
            elem = e;
            return true;
        }
    }) ? elem : null;
});

Ingatlah bahwa ini tidak bekerja pada IE8-, karena tidak mendukung some. Sebuah polyfill dapat disediakan, atau selalu ada forloop klasik :

function findElement(array, callback) {
    for (var i = 0; i < array.length; i++)
        if (callback(array[i])) return array[i];
    return null;
});

Ini sebenarnya lebih cepat dan lebih kompak. Tetapi jika Anda tidak ingin menemukan kembali roda, saya sarankan menggunakan perpustakaan utilitas seperti garis bawah atau lodash.

MaxArt
sumber
0

Terpendek,

var theAnswerObj = _.findWhere(array, {id : 42});
Manu
sumber
1
Ini memerlukan penggunaan pustaka garis bawah, OP meminta solusi javascript atau jQuery polos
Tobias Beuving
2
setelah Anda memasukkan garis bawah, ini bukan jawaban singkat!
Tim Ogilvy
-1

Pertimbangkan "axesOptions" sebagai larik objek dengan format objek menjadi {: field_type => 2,: fields => [1,3,4]}

function getFieldOptions(axesOptions,choice){
  var fields=[]
  axesOptions.each(function(item){
    if(item.field_type == choice)
        fields= hashToArray(item.fields)
  });
  return fields;
}
ramya
sumber