객체 배열에서 속성이 검색과 일치하는 객체의 색인을 찾는 가장 빠른 방법


135

나는 이것을하기위한 효율적인 방법을 찾으려고 약간의 서핑을하고 있지만 아무데도 얻지 못했습니다. 다음과 같은 객체 배열이 있습니다.

array[i].id = some number;
array[i].name = some name;

내가하고 싶은 것은 id가 0,1,2,3 또는 4와 같은 객체의 INDEXES를 찾는 것입니다. 나는 다음과 같이 할 수 있다고 가정합니다.

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

이것이 효과가 있지만, 특히 array.length가 클 수 있다면 상당히 비싸고 느리게 보입니다 (추악한 것은 말할 것도 없습니다). 이것을 조금 가려내는 방법에 대한 아이디어가 있습니까? 어떻게 든 array.indexOf를 사용하려고 생각했지만 구문을 강제하는 방법을 보지 못했습니다. 이

array.indexOf(this.id === 0);

예를 들어, 예상대로 undefined를 반환합니다. 미리 감사드립니다!


1
평범한 오래된 배열이 있다면, 반복 할 수 있습니다. 그것이 바로 배열 인덱스에 의해 정렬 된 많은 객체 인 배열입니다.
Dave Newton

2
Array.prototype.findIndex()ECMAScript 2015 에는 모든 후발 자에게 새로운 배열 방법 이 있습니다.이 답변은 정말 훌륭했습니다.
Conrad Lo

저는 ES6 구문의 팬입니다 (레거시 브라우저에서 지원이 필요한 경우 폴리 필 사용). ES7 + ES8은 미래가 될 것입니다
Fr0zenFyr

답변:


391

"map"과 같은 고차 함수를 사용하고 싶을 수도 있습니다. 'field'속성으로 검색한다고 가정합니다.

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

9
이 답변은 실제로 색인을 제공하여 질문에 대답하기 때문에 훌륭합니다. :)
Counterbeing

3
@ZeroAbsolute 적용된 함수 (맵에 전달됨)는 기준에 지정된 각 가능한 조합에 대해 고유 키를 제공해야하는 해시 문자열을 반환 할 수 있습니다. 예를 들면 다음과 같습니다 function hashf(el) { return String(el.id) + "_" + String(el.name); }.. 이것은 힌트 일뿐입니다. elementPos = array.map(hashf(x)).indexOf(hash({id:3, name:'Pablo'}));분명히 제공하는 해시 함수는 '_'값의 일부를 구성 할 수 있으므로 모든 경우에 유효 하지는 않지만 다른 해시 방법을 알아낼 수있는 간단한 예일뿐입니다.
Pablo Francisco Pérez Hidalgo

1
찾지 못하면 무엇을 반환합니까? 나는 단지 호기심이 -1이라고 가정합니다. 실험하겠습니다.
Nathan C. Tresch

1
@ NathanC.Tresch indexOf주어진 값을 찾을 수 없을 때 반환 값 이므로 -1을 반환 합니다.
Pablo Francisco Pérez Hidalgo

2
안녕하세요, 두 가지 방법을 사용하는 대신 모두 ....... map, indexOf라는 이름을 사용할 수 있습니다 findIndex. 예 :[{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3}) OR [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)
Umair Ahmed

64

배열에서 요소 인덱스를 찾는 가장 간단하고 쉬운 방법입니다.

ES5 구문 : [{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

ES6 구문 : [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)


4
이것이 가장 우아한 해결책이라고 생각합니다. 이전 버전과의 호환성이 걱정되는 사용자는 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…findIndex 에서 폴리 필을 찾을 수 있습니다.
mrogers

2
ES6 린트 도구에서 obj.id == 3여기에 사용 된 obj.id === 3연산자가 예기치 않은 유형 변환을 유발할 수 있다는 경고가 표시 되므로 대신 연산자를 사용하십시오 . 동일한 값과 유형을 테스트합니다.
thclark

1
이 답변은 위에 허용 된 답변보다 최소 3.5 배 빠릅니다. var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);그것을 사용 하는 데는 0.03500000002532033 밀리 초가 [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)걸렸습니다. 사용 하는 데는 0.00999999747378752 밀리 초가 걸렸습니다.
Ovidio Reyna

1
이 답변은 전체 배열을 반복하지 않기 때문에 가장 효율적입니다. 선택한 답변은 전체 배열을 매핑 한 다음 전체 배열을 한 번 반복하는 findIndex를 찾습니다.
Karun

26

새로운 Array 메소드 .filter () 는 다음과 같이 작동합니다.

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery는 .grep ()으로도 이를 수행 할 수 있습니다.

편집 :이 두 기능 모두 후드에서 반복된다는 점은 언급 할 가치가 있습니다. 기능과 눈에 띄는 필터 기능을 롤링하는 것 사이에는 눈에 띄는 성능 차이가 없지만 휠을 다시 발명 해야하는 이유는 무엇입니까?


+1, 나는 항상 객체에 이와 같은 내장 함수를 잊어 버립니다.
Tejs

59
인덱스를 반환하지 않습니다.
Adam Grant

이것은이 특정 질문에 대답하지 않지만 많은 도움이됩니다! 감사!
rochasdv

인덱스를 반환하지 않습니다.
Rich

10

성능에 관심이 있다면 찾기 또는 필터링 또는 매핑 하거나 위에서 설명한 방법 중 하나를 사용하지 마십시오.

다음은 가장 빠른 방법을 보여주는 예입니다. 여기 에 실제 테스트에 대한 링크가 있습니다

셋업 블록

var items = []

for(var i = 0; i < 1000; i++) {
    items.push({id: i + 1})
}

var find = 523

가장 빠른 방법

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

느린 방법

items.findIndex(item => item.id === find)

가장 느린 방법

items.map(item => item.id).indexOf(find);

2
이 비교를 제공해 주셔서 감사합니다! 가장 흥미로운 점은 어떤 브라우저 / JavaScript 엔진이 어떤 브라우저 / JavaScript 엔진을 실행했는지에 따라 더 빨리 변하는 것을 포함하여 성능이 얼마나 변하는 지입니다.
Iain Collins

1
나는 이것이 대답으로 표시되어야한다고 생각합니다. 가장 빠른 방법과 느린 방법을 보여줍니다.
진통제

벤치 마크에서, 블록 2 (findIndex 사용)가 실제로 더 빠릅니다 (Microsoft Edge Chromium 83.0.474.0에서)
rezadru

블록 2는 크롬에서도 더 빠릅니다.
cody mikol

8
array.forEach(function (elem, i) {  // iterate over all elements of array
    indexes[elem.id] = i;           // take the found id as index for the
});                                 // indexes array and assign i

결과는 id에 대한 조회 목록입니다. 주어진 ID로 레코드의 인덱스를 얻습니다.


6
var indices = [];
var IDs = [0, 1, 2, 3, 4];

for(var i = 0, len = array.length; i < len; i++) {
    for(var j = 0; j < IDs.length; j++) {
        if(array[i].id == ID) indices.push(i);
    }
}

6

일반 배열을 사용하는 답변이 없기 때문에 find:

var one = {id: 1, name: 'one'};
var two = {id: 2, name:'two'}
var arr = [one, two] 

var found = arr.find((a) => a.id === 2)

found === two // true

arr.indexOf(found) // 1

3

ES6를 사용하는 새로운 방법

let picked_element = array.filter(element => element.id === 0);

picked_element이 경우에 배열입니다 ...
Heretic Monkey

3

const index = array.findIndex(item => item.id === 'your-id');

이것은 id === your-id 인 배열의 항목 색인을 가져옵니다.

array = [ {id:1}, {id:2} ];

const index = array.findIndex(item => item.id === 2);

console.log(index);


2

테스트 콜백으로 간단한 반복자를 만들 수있는 것처럼 들립니다. 이렇게 :

function findElements(array, predicate)
{
    var matchingIndices = [];

    for(var j = 0; j < array.length; j++)
    {
        if(predicate(array[j]))
           matchingIndices.push(j);
    }

    return matchingIndices;
}

그런 다음 다음과 같이 호출 할 수 있습니다.

var someArray = [
     { id: 1, text: "Hello" },
     { id: 2, text: "World" },
     { id: 3, text: "Sup" },
     { id: 4, text: "Dawg" }
  ];

var matchingIndices = findElements(someArray, function(item)
   {
        return item.id % 2 == 0;
   });

// Should have an array of [1, 3] as the indexes that matched

2

mongoDB 및 Robomongo에 대한 Tejs의 답변에 적응하기

matchingIndices.push(j);

matchingIndices.push(NumberInt(j+1));

2

ES6 map기능 사용 :

let idToFind = 3;
let index = someArray.map(obj => obj.id).indexOf(idToFind);

2

위의 모든 위대한 답변과 내 답변의 추가 사항을 요약하면 일부 의견에서 모든 색인을 찾았습니다.

  1. 첫 번째 발생 색인을 반환합니다.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }];
const idYourAreLookingFor = 2;

//ES5 
//Output: 1
array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor);

//ES6 
//Output: 1
array.findIndex(obj => obj.id === idYourAreLookingFor);

  1. reduce를 사용하여 모든 항목의 인덱스 배열을 리턴합니다.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }]
const idYourAreLookingFor = 2;

//ES5
//Output: [1, 4]
array.reduce(function (acc, obj, i) {
  if (obj.id === idYourAreLookingFor)
    acc.push(i);
  return acc;
}, []);

//ES6
//Output: [1, 4]
array.reduce((acc, obj, i) => (obj.id === idYourAreLookingFor) ? acc.concat(i) : acc, [])


0

아직 언급 할 수 없으므로 Umair Ahmed가 게시 한 방법을 기반으로 사용한 솔루션을 보여주고 싶지만 값 대신 키를 검색하려는 경우 :

[{"a":true}, {"f":true}, {"g":false}]
.findIndex(function(element){return Object.keys(element)[0] == "g"});

나는 그것이 확장 된 질문에 대답하지는 않지만 제목은 각 객체에서 원하는 것을 지정하지 않기 때문에 미래에 다른 사람들에게 두통을 줄이기 위해 겸손히 공유하고 싶습니다. 가장 빠른 솔루션.


0

O (1) 복잡도를 가진 고유 식별자로 배열의 항목에 액세스 할 수있는 슈퍼 어레이 라는 작은 유틸리티를 만들었습니다 . 예:

const SuperArray = require('super-array');

const myArray = new SuperArray([
  {id: 'ab1', name: 'John'},
  {id: 'ab2', name: 'Peter'},
]);

console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'}
console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'}

개인 오픈 소스 라이브러리를 제공하는 방법 을 읽어보십시오 . 이것을 사방에 게시하기 전에.
Martijn Pieters

@MartijnPieters 나는 몇 가지 관련 질문에만 게시했으며 프로젝트는 MIT 무료이므로 거래는 무엇입니까? 어쩌면 당신은 조금 더 관대 할 수 있습니다.
patotoma

0
var test = [
  {id:1, test: 1},
  {id:2, test: 2},
  {id:2, test: 2}
];

var result = test.findIndex(findIndex, '2');

console.log(result);

function findIndex(object) {
  return object.id == this;
}

인덱스 1을 반환합니다 (ES 2016에서만 작동)


0

개체의 깊이에 관계없이 개체의 모든 값과 비교하기 쉽기 때문에이 방법이 마음에 듭니다.

 while(i<myArray.length && myArray[i].data.value!==value){
  i++; 
}
// i now hows the index value for the match. 
 console.log("Index ->",i );
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.