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


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.