etc./StackOverFlow

JavaScript 객체 배열에서 id로 객체 찾기

청렴결백한 만능 재주꾼 2022. 1. 2. 04:54
반응형

질문자 :thugsb


배열이 있습니다.

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

배열의 구조를 변경할 수 없습니다. 45 가 전달되고 있으며 배열의 해당 객체에 대한 'bar' 를 얻고 싶습니다.

JavaScript 또는 jQuery를 사용하여 이 작업을 수행하려면 어떻게 해야 합니까?



find() 메서드를 사용합니다.

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

MDN에서 :

find() 메서드는 배열의 요소가 제공된 테스트 기능을 충족하는 경우 배열의 첫 번째 값을 반환합니다. 그렇지 않으면 undefined 가 반환됩니다.


대신 인덱스 를 찾으려면 findIndex() 사용하십시오.

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

MDN에서 :

findIndex() 메서드는 제공된 테스트 기능을 만족하는 배열의 첫 번째 요소의 인덱스를 반환합니다. 그렇지 않으면 -1이 반환됩니다.


일치하는 요소의 배열을 얻으려면 filter() 메서드를 사용하십시오.

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

이것은 객체의 배열을 반환할 것입니다. foo 속성의 배열을 얻으려면 map() 메서드를 사용하여 이 작업을 수행할 수 있습니다.

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

참고 사항: find() 또는 filter() 와 같은 메서드 및 화살표 기능 은 IE와 같은 이전 브라우저에서 지원되지 않으므로 이러한 브라우저를 지원하려면 Babel ( polyfill 포함 )을 사용하여 코드를 변환해야 합니다.


Michał Perłakowski

이미 jQuery를 사용하고 있으므로 배열 검색을 위한 grep 함수를 사용할 수 있습니다.

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

결과는 찾은 항목이 있는 배열입니다. 객체가 항상 거기에 있고 한 번만 발생한다는 것을 알고 있다면 result[0].foo 를 사용하여 값을 얻을 수 있습니다. 그렇지 않으면 결과 배열의 길이를 확인해야 합니다. 예시:

 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

또 다른 솔루션은 조회 개체를 만드는 것입니다.

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

이것은 많은 조회를 수행해야 하는 경우에 특히 흥미롭습니다.

ID와 개체가 공유되므로 더 많은 메모리가 필요하지 않습니다.


Aaron Digulla

ECMAScript 2015 (JavaScript ES6)는 배열에 대한 find() 메서드를 제공합니다.

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

외부 라이브러리 없이 작동합니다. 그러나 이전 브라우저 지원 을 원하면 이 폴리필 을 포함할 수 있습니다.


Rúnar Berg

Underscore.js 에는 다음과 같은 좋은 방법이 있습니다.

 myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.] obj = _.find(myArray, function(obj) { return obj.id == '45' })

GijsjanB

가장 쉬운 방법은 다음과 같을 것이라고 생각하지만 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

pimvdb

다음을 시도하십시오

 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

myArray.filter(function(a){ return a.id == some_id_you_want })[0]

Danilo Colasso

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

will Farrell

성능

오늘 2020.06.20 선택한 솔루션에 대해 Chrome 81.0, Firefox 77.0 및 Safari 13.1의 MacOs High Sierra에서 테스트를 수행합니다.

사전 계산을 사용하는 솔루션에 대한 결론

사전 계산(K,L)이 있는 솔루션은 다른 솔루션보다 (훨씬) 빠르며 비교되지 않습니다. 아마도 특별한 내장 브라우저 최적화를 사용하는 것 같습니다.

  • 놀랍게도 Chrome 및 Safari에서 Map {} (L) 개체 기반 솔루션보다 훨씬 빠릅니다.
  • {} (L)를 기반으로 하는 소규모 배열 솔루션의 경우 Safari for (E)의 경우 기존보다 느립니다.
  • Map (K) 기반의 소규모 어레이 솔루션 for (E)의 기존 솔루션보다 느립니다.

검색된 개체가 항상 존재할 때의 결론

  • for 전통적인 것을 사용하는 솔루션은 작은 어레이에 대해 가장 빠르고 큰 어레이에 대해 빠릅니다.
  • 캐시(J)를 사용하는 솔루션은 큰 어레이의 경우 가장 빠릅니다. 놀랍게도 작은 어레이의 경우 중간 정도 빠릅니다.
  • find (A) 및 findIndex (B)를 기반으로 하는 솔루션은 작은 어레이의 경우 빠르고 큰 어레이의 경우 중간 속도입니다.
  • $.map (H) 기반 솔루션은 작은 배열에서 가장 느립니다.
  • 에 기반 솔루션 reduce (D)의 큰 배열에 대한 느린입니다

여기에 이미지 설명 입력

검색된 개체가 절대 존재하지 않을 때의 결론

  • 전통에 기반 솔루션 for (이 두 번째 빠른 곳 크롬 작은 배열 제외) (E)는 크고 작은 배열에 가장 빠른
  • 에 기반 솔루션 reduce (D)의 큰 배열에 대한 느린입니다
  • 캐시(J)를 사용하는 솔루션은 중간 정도 빠르지만 null 값이 있는 키도 캐시에 저장하면 속도가 빨라질 수 있습니다. 검색하다)

여기에 이미지 설명 입력

세부

솔루션용

  • 사전 계산 없이: A B C D E F G H I J (J 솔루션은 '내부' 캐시를 사용하며 속도는 검색된 요소가 얼마나 자주 반복되는지에 따라 다릅니다)
  • 사전 계산 K L

네 가지 테스트를 수행합니다. 테스트에서 10번의 루프 반복에서 5개의 객체를 찾고 싶습니다(객체 ID는 반복 중에 변경되지 않음). 따라서 테스트된 메서드를 50번 호출하지만 처음 5번만 고유한 id 값을 가집니다.

테스트된 코드는 아래에 나와 있습니다.

 function A(arr, id) { return arr.find(o=> o.id==id); } function B(arr, id) { let idx= arr.findIndex(o=> o.id==id); return arr[idx]; } function C(arr, id) { return arr.filter(o=> o.id==id)[0]; } function D(arr, id) { return arr.reduce((a, b) => (a.id==id && a) || (b.id == id && b)); } function E(arr, id) { for (var i = 0; i < arr.length; i++) if (arr[i].id==id) return arr[i]; return null; } function F(arr, id) { var retObj ={}; $.each(arr, (index, obj) => { if (obj.id == id) { retObj = obj; return false; } }); return retObj; } function G(arr, id) { return $.grep(arr, e=> e.id == id )[0]; } function H(arr, id) { return $.map(myArray, function(val) { return val.id == id ? val : null; })[0]; } function I(arr, id) { return _.find(arr, o => o.id==id); } let J = (()=>{ let cache = new Map(); return function J(arr,id,el=null) { return cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el); } })(); function K(arr, id) { return mapK.get(id) } function L(arr, id) { return mapL[id]; } // ------------- // TEST // ------------- console.log('Find id=5'); myArray = [...Array(10)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`})); const mapK = new Map( myArray.map(el => [el.id, el]) ); const mapL = {}; myArray.forEach(el => mapL[el.id]=el); [A,B,C,D,E,F,G,H,I,J,K,L].forEach(f=> console.log(`${f.name}: ${JSON.stringify(f(myArray, '5'))}`)); console.log('Whole array',JSON.stringify(myArray));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script> This snippet only presents tested codes

검색된 개체가 항상 존재하는 작은 배열에 대한 Chrome 테스트 결과의 예

여기에 이미지 설명 입력


Kamil Kiełczewski

이 작업을 여러 번 수행하면 맵(ES6)을 설정할 수 있습니다.

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

그런 다음 간단히 O(1) 조회를 수행할 수 있습니다.

 map.get(27).foo

Jonas Wilms

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

작업 예: http://jsfiddle.net/hunter/Pxaua/


hunter

필터를 사용할 수 있으며,

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

Joe Lewis

기본 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) });

발견되면 객체 요소를 반환하고 그렇지 않으면 false


laggingreflex

여기에는 많은 정답이 있지만 대부분은 이것이 두 번 이상 수행하면 불필요하게 비용이 많이 드는 작업이라는 사실을 다루지 않습니다. 극단적인 경우 실제 성능 문제의 원인이 될 수 있습니다.

실제 세계에서 많은 항목을 처리하고 성능이 문제인 경우 처음에 조회를 빌드하는 것이 훨씬 빠릅니다.

 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


Tom

최근에 나는 거대한 배열에서 문자열을 검색해야 하는 것과 같은 일에 직면해야 합니다.

몇 가지 검색 후 간단한 코드로 처리하기 쉽습니다.

암호:

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

https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/ 참조

20k 문자열에서 검색


maheshwaghmare

브라우저가 ECMA-262 , 5판(2009년 12월)을 지원하는 한 거의 한 줄로 작동합니다.

 var bFound = myArray.some(function (obj) { return obj.id === 45; });

aggaton

ECMAScript 3 이상에서 작동한다고 생각할 수 있는 가장 최소한의 방식으로 순수 JavaScript로 처리하는 방법은 다음과 같습니다. 일치하는 항목이 발견되는 즉시 반환됩니다.

 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

보다 일반적이고 짧은

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

귀하의 경우 예. var element = findFromArray(myArray,'id',45) 전체 요소를 제공합니다.


Savan Kaneriya

배열의 모든 항목을 반복합니다. 방문하는 모든 항목에 대해 해당 항목의 ID를 확인하십시오. 일치하는 경우 반환합니다.

당신이 테코데즈를 원한다면:

 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의 Array 메소드를 사용하는 것과 같은 것:

 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

http://sugarjs.com/ 에서 Sugarjs를 사용해 볼 수 있습니다.

.find 에 대한 매우 달콤한 방법을 가지고 있습니다. 따라서 다음과 같은 요소를 찾을 수 있습니다.

 array.find( {id: 75} );

또 다른 "where-clause"를 추가하기 위해 더 많은 속성을 가진 객체를 전달할 수도 있습니다.

Sugarjs는 기본 객체를 확장하고 어떤 사람들은 이것을 매우 악하다고 생각합니다...


deepflame

Jquery 메소드를 사용할 수 있습니다. $.each()/$.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

또는 Lodash https://lodash.com/docs/4.17.10#filter , 밑줄 https://underscorejs.org/#filter 사용


TLbiz

다른 사람들이 지적했듯이 .find() 는 배열 내에서 하나의 객체를 찾을 때 사용하는 방법입니다. 그러나 이 방법을 사용하여 개체를 찾을 수 없으면 프로그램이 충돌합니다.

 const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]; const res = myArray.find(x => x.id === '100').foo; // Uh oh! /* Error: "Uncaught TypeError: Cannot read property 'foo' of undefined" */

.foo 를 사용하기 전에 .find() 의 결과가 정의되었는지 확인하여 수정할 수 있습니다. Modern JS를 사용하면 코드를 충돌시키지 않고 객체를 찾을 수 없는 경우 undefined 반환 하는 선택적 chaining 을 사용하여 이 작업을 쉽게 수행할 수 있습니다.

 const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]; const res = myArray.find(x => x.id === '100')?.foo; // No error! console.log(res); // undefined when the object cannot be found


Nick Parsons

허용된 답변을 바탕으로 다음을 수행합니다.

제이쿼리:

 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

stevenspiel

Array.prototype.filter() 함수를 사용합니다.

데모 : 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 } } ];

필터

 var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.name === name; }); }

Sumit Ridhal

배열에 내장된 "필터" 기능을 사용하여 순수한 JavaScript에서도 이 작업을 수행할 수 있습니다.

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

key 대신 "id"를 value 대신 "45"를 전달하면 id 45와 일치하는 전체 객체를 얻을 수 있습니다.

 myArr.filterObjects("id", "45");

kaizer1v

Aaron 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


quincyaft

사용하다:

 var retObj ={}; $.each(ArrayOfObjects, function (index, obj) { if (obj.id === '5') { // id.toString() if it is int retObj = obj; return false; } }); return retObj;

id로 객체를 반환해야 합니다.


volumexxx

이 솔루션은 다음과 같은 경우에도 도움이 될 수 있습니다.

 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 처럼 만들었는데 하나의 객체가 발견되면 함수 는 배열이 아닌 객체를 반환합니다.


soytian

동적 캐시 찾기

이 솔루션에서는 어떤 객체를 검색할 때 캐시에 저장합니다. 이것은 "항상 검색 솔루션"과 "사전 계산에서 각 개체에 대한 해시 맵 생성" 사이의 중간 지점입니다.

 let cachedFind = (()=>{ let cache = new Map(); return (arr,id,el=null) => cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el); })(); // --------- // TEST // --------- let myArray = [...Array(100000)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`})); // example usage console.log( cachedFind(myArray,'1234').foo ); // Benchmark let bench = (id) => { console.time ('time for '+id ); console.log ( cachedFind(myArray,id).foo ); // FIND console.timeEnd('time for '+id ); } console.log('----- no cached -----'); bench(50000); bench(79980); bench(99990); console.log('----- cached -----'); bench(79980); // cached bench(99990); // cached


Kamil Kiełczewski

출처 : http:www.stackoverflow.com/questions/7364150/find-object-by-id-in-an-array-of-javascript-objects

반응형