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


1545

배열이 있습니다.

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

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

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

답변:


1187

find()방법을 사용하십시오 :

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

에서 MDN :

find()있어서, 상기 어레이의 제 1 값을 반환 배열에 만족하는 요소가 제공하는 기능을 테스트하는 경우. 그렇지 않으면 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 포함 )을 사용하여 코드를 변환해야합니다 .


2
여러 테스트 조건의 경우 다음과 같습니다. myArray.find (x => x.id === '45'&& x.color == 'red'). foo
Apqu

2
나를 위해, 지금까지 최선의 답변. 새로운 보조 배열을 생성하거나 jQuery를 필요로하지 않습니다.
Canta

myArray.find (X => x.id === '45')는 맥 PC에서 작동하지 않습니다
고빈다 Rajbhar

@TJCrowder MDN의 폴리 필을 코드에 복사하여 붙여 넣는 것은 좋은 생각이 아닙니다. 대신, 폴리 필과 함께 npm 패키지를 사용해야합니다. 그리고 Babel은 babel-polyfill 패키지 에 ES2015 + 기능을위한 polyfill을 포함 합니다.
Michał Perłakowski 2016 년

2
myArray.find (x => x.id === '45'). foo; id가 '45'인 객체가 없으면 예외가 발생합니다.
Frazer Kirkman

1466

이미 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
}

124
JavaScript 연산자 의 이상한 문제를 피 하려면 ===대신 대신 사용 하는 것이 더 안전합니다 . ====
Vicky Chijwani

11
@VickyChijwani : 문자열을 문자열과 비교할 때 문제가 있습니까?
Guffa December

38
당신이 있다면 글쎄, 절대적으로 모두 확인 e.id하고 id문자열이 될 것입니다, 내가 사용에 그것의 확인을 가정한다 ==. 확실하지 않은 경우 (이후, 당신은 문제에 직면 할 수 '' == 0있습니다 true'' === 0입니다 false). 말할 것도없고 ===더 빠릅니다 ( stackoverflow.com/questions/359494/… ).
Vicky Chijwani

101
기본적으로 항상 다른 프로그래밍 언어 와 동일=== 하게 작동 하기 때문에 항상 사용 합니다. JavaScript에 존재하지 않는 것으로 간주 합니다. ====
Vicky Chijwani

6
@de. 여기에 많은 답변이 고유 한 값을 찾을 때 의도 된 동작을 제공합니다. 루프에서 일찍 리턴하거나 중단한다는 사실로 기본적으로이를 인식 할 수 있습니다 (또는 하위 레벨 구성에 반복 중지를 지시하십시오). 정식 예제는 JaredPar의 답변과 같은 통찰력에 대한 Aaronius의 의견을 참조하십시오. 일반적으로 사람들은 이런 방식으로 "필터"와 "찾기"기능을 구분하지만 용어는 다양합니다. 더 효율적이지만 여전히 선형 검색이므로 해시 테이블을 사용하려면 Aaron Digulla의 답변을 참조하십시오 (임시 정보).
tne

362

또 다른 해결책은 조회 오브젝트를 작성하는 것입니다.

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와 객체가 공유되므로 더 많은 메모리가 필요하지 않습니다.


6
정확히 내가 찾던 것. CouchDB에서 수신 된 데이터를 변경하고 필요한 형식으로 가져와야 할 때 발견 한대로 매번 반복하여 목록에서 각 항목을 제거하여 과도하게 복잡하게하려고하는 재미있는 방법 필요합니다. +1 선생님!
slickplaid

5
똑똑하다. 각 용도에 대해 어레이 전체를 살펴봄으로써 다른 사람들이 어떻게 확신했는지 상상할 수 없습니다.
Aladdin Mhemed

4
속성 순서에 의존하지 않는 한 : stackoverflow.com/questions/4886314/…
Marle1

휴식을 사용하고 있습니다. 루프에서 찾을 객체가 하나뿐이라는 것을 알고 있다면 좋은 옵션 / 개선입니까?
irJvV

7
@irJvV : 아니요, 전혀 이해가되지 않습니다. 위의 코드는 많은 조회를 수행해야하는 경우에 유용합니다. 한 번만 살펴보면 lookup객체 를 만드는 것이 시간 낭비입니다.
Aaron Digulla

174

ECMAScript 2015 는 배열 에서 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);

외부 라이브러리없이 작동합니다. 그러나 이전 브라우저 지원 을 원할 경우이 polyfill 을 포함시킬 수 있습니다 .


1
아마도 여전히 매우 실험적인 것처럼 보이고 많은 브라우저에서 지원하지는 않습니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
lejonl

2
이것은로 단순화 될 수 있습니다 myArray.find(d=>d.id===45).foo;.
얽히고 설킨

1
@Shaggy 또는 myArray.find(({ id }) => id === 45).foo. 그러나 이것은 ES2015 구문이 지금처럼 잘 지원되기 전에 작성된 오래된 대답입니다. @Gothdo의 답변 은 현재 스레드에서 가장 최신입니다.
Rúnar Berg

1
@Shaggy .find ()가 undefined를 반환하면 최적화에서 오류가 발생합니다. 따라서이 솔루션은 일치가 보장되는 경우에만 사용할 수 있습니다.
허버트 피터스

1
@HerbertPeters 만약 당신이 항상 null-check를 할 수있게하려면, 선택적인 chaining 으로 정말 쉬울 것이다 : myArray.find(d => d.id === 45)?.foo.
Rúnar Berg

141

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

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

42
레코드의 경우 Lo-Dash (보통 Underscore보다 성능이 뛰어남)도 비슷한 방법을 사용합니다. 여기 문서 : lodash.com/docs#find
user456584

하나의 객체 만 예상한다면 findWhere를 사용하는 것이 하나의 결과를 찾은 후보다 효율적일 수 있습니다.
Foreever

@Foreever _.find 문서에서 : "이 함수는 수용 가능한 요소를 찾 자마자 반환하고 전체 목록을 탐색하지 않습니다."
GijsjanB

129

가장 쉬운 방법은 다음과 같지만 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

궁금합니다. 평소에 비해 여기에 성능상의 이점이 for있습니까?
Igor Zinov'yev

@Igor Zinov'yev : 예. ES5 어레이 도구의 성능에 확실히 영향을 미칩니다. 각 요소에 대해 별도의 기능이 실행되므로 직접 for루프 와 비교할 때 실제로 빠르지는 않습니다 .
pimvdb

그래서 당신은 그것이 더 느릴 것이라고 말하고 있습니까? 또한, 내가 볼 수있는 한 항상 전체 배열을 스캔하지만 for루프는 첫 번째 일치에서 종료됩니다.
Igor Zinov'yev


이 코드에는 요소가없는 경우 오류가 발생합니다id
Stan

71

다음을 시도하십시오

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

17
이것은 자체 답변에 합당하지는 않았지만 최신 브라우저에서는이 솔루션을 다음과 같이 작성할 수 있습니다. jsfiddle.net/rwaldron/j3vST
Rick

12
효율성을 얻으려면이 예제는 filter () (Rick의 예제 참조)를 사용하는 것보다 빠릅니다. 첫 번째 일치 항목을 찾으면 filter ()는 전체 배열을 통해 계속 실행하기 때문입니다. 시합. 또한 추가 배열을 만들거나 각 항목에 대해 함수를 호출하는 비용이 없습니다.
Aaronius

3
@Rick, 그 답변에 대한 가장 흥미로운 점은 분명히 jsFiddle의 출력 창에 firebug 콘솔을 추가 할 수 있다는 것입니다. 이것은 로깅을하고 다른 사람에게 콘솔을 열어 출력을 보도록 지시하는 것보다 훨씬 낫습니다. 대박!
KyleMit

1
지금까지 아무도 언급하지 않았으므로 AngularJS에도 필터 방법 이 있다고 덧붙이고 싶습니다 .
Eno



31

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

15

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/


1
jQuery가 map자동으로 null요소를 제거 한다는 사실을 잊었습니다 . map결과가 원본 컬렉션의 길이와 같지 않기 때문에 나에게 일반적인 개념으로 오해하는 것처럼 들립니다 .
MaxArt

14

필터를 사용할 수 있습니다.

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

get_my_obj = getById(73, myArray);

1
@TobiasBeuving-Array.find ()를 사용하는 것은 일반 JS이므로 첫 번째 찾기에서 중지해야하므로보다 효율적입니다.
Adrian Lynch

12

여기에는 많은 정답이 있지만, 그 중 다수는 이것이 한 번 이상 수행되는 경우 불필요하게 비싼 작업이라는 사실을 다루지 않습니다. 극단적 인 경우 실제 성능 문제의 원인 일 수 있습니다.

실제 환경에서 많은 항목을 처리하고 성능이 문제가되는 경우 처음에 조회를 작성하는 것이 훨씬 빠릅니다.

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을 객체로 사용하는 대신 맵을 사용할 수도 있습니다.


11

네이티브 사용 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


참고로 Array.reduce는 IE8 이하에서 지원되지 않습니다.
Burn_E99

7

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

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

그런 다음 간단히 할 수 있습니다.

map.get(27).foo

6

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'

5

보다 일반적이고 짧은

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

귀하의 경우에는 Ex. var element = findFromArray(myArray,'id',45)그것은 당신에게 모든 요소를 ​​줄 것입니다.


4

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

Arrays에는 매우 달콤한 방법이 있습니다 .find. 따라서 다음과 같은 요소를 찾을 수 있습니다.

array.find( {id: 75} );

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

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


2
음, 그것은 이다 새로운 ECMA 스크립트 버전은 같은 이름의 새로운 방법을 도입 할 수 있음을 발생할 수 있기 때문에, 악. 그리고 이것이 무엇인지 정확히find 추측하십시오 . 내 제안은 기본 프로토 타입을 확장하려면 항상 더 구체적인 이름을 사용하고 가장 간단한 이름은 향후 표준 개발에 남겨 두는 것입니다.
MaxArt

이 의견은 거의 2 세이며 오늘은 어쨌든 lodash를 사용하려고합니다. 그러나 원하는 경우 sugarjs 웹 사이트에서이 주제에 대해 읽을 수 있습니다. 그들은 당신의 의견에 잘 견딘다
deepflame

1
작전은 특별히 자바 스크립트 또는 jquery 솔루션을 요청했습니다
Tobias Beuving

4

허용 된 답변을 바탕으로 :

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

4

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

몇 가지 검색 후 간단한 코드로 쉽게 처리 할 수 ​​있습니다.

암호:

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

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

20k 현에서 봉사


3

배열의 모든 항목을 반복하십시오. 방문하는 모든 항목에 대해 해당 항목의 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];
}

3

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

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

2
거의. 요소가 필요한 조건을 충족시키는 경우 bFound부울입니다 true.
MaxArt

3

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

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

이제 대신 "id"대신 key"45" 를 전달하면 id 45 value와 일치하는 전체 객체를 얻게됩니다.

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

16
소유하지 않은 개체는 수정하지 마십시오.
Michał Perłakowski 2019

3

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

중첩 된 객체 내에서 어떻게 검색 할 수 있습니까? pets = false와 같이 두 개의 객체를 반환해야합니다.
Valay

중첩 루프에서 .filter메소드를 사용하십시오 obj.info. var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
Sud Ridhal

당신은 너무 IMO ES6 스타일을 사용할 수 있습니다 ... CONST의 FilterData = jsonObj.filter (OBJ => obj.name === '알렉스')
DagicCross


2

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


배열에서 항목을 찾는 데 가장 빠른 솔루션과 동일한 솔루션을 사용했습니다. 그러나 parseInt는 여기서 중복됩니다.
aleha

1

사용하다:

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

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

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

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


return obj.id === 5를 사용하여 코드를 줄일 수 있습니까? obj : 거짓; 배열을 반복하는 데 $ .each를 많이 사용합니다.
marcel

@ marcel : 작동하지 않습니다. false를 반환하면 루프가 종료되므로 객체가 배열의 첫 번째 항목 인 경우에만 객체를 찾습니다.
Guffa

1

이 솔루션도 도움이 될 수 있습니다.

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


2
소유하지 않은 개체는 수정하지 마십시오.
Michał Perłakowski 2019

@Gothdo 동의합니다. 누군가 알지 못하면 function will return the object, rather than an array실수 가 발생할 수 있지만 사용자에게 달려 있다고 생각합니다.
soytian

0

aggaton 's answer 에서 시작 하여 "correct"요소에 대해 정확한 값을 반환하는 함수 와 null주어진 함수를 사용하여 원하는 요소를 실제로 반환하는 함수입니다 (또는 찾을 수없는 경우) .arraycallback

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

실제로 더 빠르고 컴팩트합니다. 그러나 바퀴를 재발 명하고 싶지 않다면 밑줄이나 lodash와 같은 유틸리티 라이브러리를 사용하는 것이 좋습니다.


0

최단,

var theAnswerObj = _.findWhere(array, {id : 42});

1
이를 위해서는 언더 스코어 라이브러리를 사용해야하며 OP는 일반 자바 스크립트 또는 jQuery 솔루션을 요청했습니다.
Tobias Beuving

2
밑줄을 포함하면 짧은 답변이 아닙니다!
Tim Ogilvy

-1

"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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.