Найти объект по идентификатору в массиве объектов JavaScript
у меня есть массив:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]
Я не могу изменить структуру массива. Мне передают идентификатор 45 и я хочу сделать 'bar' для этого объекта в массиве.
как это сделать в JavaScript или с помощью jQuery?
29 ответов:
использовать
find()способ:myArray.find(x => x.id === '45').foo;С MDN:
The
find()метод возвращает значение в массиве, если элемент в массиве удовлетворяет предусмотрена функция тестирования. В противном случаеundefinedвозвращается.
если вы хотите найти свою индекс вместо этого используйте
findIndex():myArray.findIndex(x => x.id === '45');С MDN:
The
findIndex()способ возвращает индекс первого элемента в массиве, который удовлетворяет предусмотрена функция тестирования. В противном случае возвращается значение -1.
если вы хотите получить массив совпадающих элементов, используйте
filter()метод вместо этого:myArray.filter(x => x.id === '45');это вернет массив объектов. Если вы хотите получить массив
fooсвойства, вы можете сделать это с помощьюmap()способ:myArray.filter(x => x.id === '45').map(x => x.foo);
Примечание: такие методы, как
find()илиfilter()и функции стрелочку не поддерживаются старыми браузерами (например, IE), поэтому, если вы хотите поддерживать эти браузеры, вы должны транспилировать свой код с помощью Бабель (С полифилл).
как вы уже используете jQuery, вы можете использовать grep функция, которая предназначена для поиска массива:
var result = $.grep(myArray, function(e){ return e.id == id; });результатом является массив с найденными элементами. Если вы знаете, что объект всегда есть, и что это происходит только один раз, вы можете просто использовать
result[0].fooчтобы получить значение. В противном случае вы должны проверить длину результирующего массива. Пример:if (result.length == 0) { // not found } else if (result.length == 1) { // access the foo property using result[0].foo } else { // multiple items found }
другое решение заключается в создании объекта поиска:
var lookup = {}; for (var i = 0, len = array.length; i < len; i++) { lookup[array[i].id] = array[i]; } ... now you can use lookup[id]...Это особенно интересно, если вам нужно сделать много просмотров.
Это не понадобится гораздо больше памяти, так как идентификаторы и объекты будут разделены.
ECMAScript 2015 предоставляет найти() метод с массивами:
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);Он работает без внешних библиотек. Но если вы хотите поддержка старых браузеров вам понадобится этот полифилл.
подчеркивания.js имеет хороший метод для этого:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.] obj = _.find(myArray, function(obj) { return obj.id == '45' })
Я думаю, что самый простой способ будет следующим, но он не будет работать в Internet Explorer 8 (или ранее):
var result = myArray.filter(function(v) { return v.id === '45'; // Filter out the appropriate one })[0].foo; // Get result and access the foo property
попробуйте следующее
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; }
общая и более гибкая версия функции findById выше:
// 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');
вы можете использовать фильтры,
function getById(id, myArray) { return myArray.filter(function(obj) { if(obj.id == id) { return obj } })[0] } get_my_obj = getById(73, myArray);
вы можете сделать это легко с помощью 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";
использование уроженца
Array.reducevar 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) });возвращает элемент объекта, если он найден, в противном случае
false
хотя здесь есть много правильных ответов, многие из них не касаются того факта, что это неоправданно дорогая операция, если она выполняется более одного раза. В крайнем случае это может быть причиной реальных проблем с производительностью.
в реальном мире, если вы обрабатываете много элементов и производительность является проблемой, это гораздо быстрее, чтобы изначально построить поиск:
var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]; var lookup = items.reduce((o,i)=>o[i.id]=o,{});вы можете получить на элементы в фиксированное время, как это:
var bar = o[id];вы может также рассмотреть возможность использования карты вместо объекта в качестве поиска: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
Вы можете попробовать Sugarjs от http://sugarjs.com/.
Он имеет очень сладкий метод на массивах,
.find. Таким образом, вы можете найти такой элемент:array.find( {id: 75} );вы также можете передать объект с большим количеством свойств к нему, чтобы добавить еще один "где-предложение".
обратите внимание, что Sugarjs расширяет родные объекты, и некоторые люди считают это очень злом...
основываясь на принятом ответе:
jQuery:
var foo = $.grep(myArray, function(e){ return e.id === foo_id}) myArray.pop(foo)Или CoffeeScript:
foo = $.grep myArray, (e) -> e.id == foo_id myArray.pop foo
вот как я бы сделал это в чистом JavaScript, самым минимальным образом, который я могу придумать, который работает в ECMAScript 3 или более поздней версии. Он возвращается, как только совпадение найдено.
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'
Если вы делаете это несколько раз, вы можете настроить карту (ES6):
const map = new Map( myArray.map(el => [el.id, el]) );затем вы можете просто сделать:
map.get(27).foo
вы можете сделать это даже в чистом JavaScript, используя встроенную функцию "фильтр" для массивов:
Array.prototype.filterObjects = function(key, value) { return this.filter(function(x) { return x[key] === value; }) }так что теперь просто передайте " id " вместо
keyи "45" вместоvalue, и вы получите полный объект, соответствующий идентификатору 45. Так и будет,myArr.filterObjects("id", "45");
Мне очень понравился ответ Аарон Digulla, но необходимо, чтобы сохранить мой массив объектов, чтобы я мог перебирать его позже. Поэтому я изменил его на
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
перебрать любой элемент в массиве. Для каждого элемента, который вы посещаете, проверьте идентификатор этого элемента. Если это совпадение, верните его.
Если вы просто хотите ТЭН codez:
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 }и то же самое с использованием методов массива 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]; }
пока браузер поддерживает ECMA-262, 5-е издание (декабрь 2009), это должно работать, почти один лайнер:
var bFound = myArray.some(function (obj) { return obj.id === 45; });
использование:
var retObj ={}; $.each(ArrayOfObjects, function (index, obj) { if (obj.id === '5') { // id.toString() if it is int retObj = obj; return false; } }); return retObj;он должен возвращать объект по идентификатору.
это решение также может быть полезно:
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");Я сделал это так же, как
$.grepи если один объект узнайте, функции вернет объект, а не массив.
начиная от aggaton это, это функция, которая фактически возвращает нужный элемент (или
nullесли не нашли), учитываяarrayиcallbackфункция, которая возвращает истинное значение для "правильного" элемента:function findElement(array, callback) { var elem; return array.some(function(e) { if (callback(e)) { elem = e; return true; } }) ? elem : null; });просто помните, что это изначально не работает на IE8 -, так как он не поддерживает
some. Полифилл может быть предоставлен, в качестве альтернативы всегда есть классическийforпетли:function findElement(array, callback) { for (var i = 0; i < array.length; i++) if (callback(array[i])) return array[i]; return null; });это на самом деле быстрее и более компактный. Но если вы не хотите изобретать велосипед, я предлагаю использовать служебную библиотеку, такую как underscore или lodash.
считайте, что "axesOptions" - это массив объектов с форматом объекта {: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; }
мы можем использовать методы Jquery $.каждый.$/)(команда grep()
var data= []; $.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}или
var data = $.grep(array, function( n, i ) { return ( n !== 5 && i > 4 ); });использовать синтаксис ES6:
Array.find, Array.filter, Array.forEach, Array.mapили использовать Лодаш https://lodash.com/docs/4.17.10#filter, подчеркивание https://underscorejs.org/#filter
используйте метод фильтра jQuery:
$(myArray).filter(function() { return this.id == desiredId; }).first();это вернет первый элемент с указанным идентификатором.
Он также имеет преимущество хорошего формата C# LINQ.
Comments