객체 배열의 indexOf 메소드?


512

객체를 포함하는 배열의 인덱스를 얻는 가장 좋은 방법은 무엇입니까?

이 시나리오를 상상해보십시오.

var hello = {
    hello: 'world',
    foo: 'bar'
};
var qaz = {
    hello: 'stevie',
    foo: 'baz'
}

var myArray = [];
myArray.push(hello,qaz);

이제이 예제에서 indexOf어떤 hello속성이 'stevie'어떤 객체인지 확인 하고 싶습니다 1.

나는 JavaScript를 처음 접하는 초보자이며 간단한 방법이 있는지 또는 그렇게하기 위해 내 자신의 함수를 만들어야하는지 모르겠습니다.


1
당신은 두 개체 병합 하시겠습니까 hello과를 qaz?
— Armin

아뇨 배열에 객체 목록을 갖고 싶습니다.
— Antonio Laguna

아 알았어! 정의 된 속성이있는 배열에서 전체 객체의 위치를 ​​알고 싶습니다.
— Armin

10
이 SO 답변 으로이 정확한 문제를 해결하는 매우 간단한 기능을 찾았습니다. var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor); var objectFound = array[elementPos]; [link] ( stackoverflow.com/a/16100446/1937255 )
— Rick

ES6 Array.indexOf가 허용 된 답변보다 낫습니다 (ES6이 효과가있는 경우)-아래의 전체 예를 참조하십시오
— yar1

답변:


1043

map 함수를 사용하여 한 줄로 해결할 수 있다고 생각합니다 .

pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');

58
이것은 정직하게 받아 들여지는 대답이어야합니다. 대부분의 브라우저는 현재 지원Array.prototype.map()
— AlbertEngelB

10
IE8에서는 지원되지 않지만 문제가되지 않으면 이것이 최선의 해결책입니다.
— 안토니오 라구나

57
음 ... Array.prototype.map ()은 매핑 된 항목을 포함하는 완전히 새로운 배열을 생성한다는 점에 주목할 가치가 있습니까? 따라서 1000 개의 요소가있는 배열이 있다면 먼저 1000 개의 요소로 다른 배열을 만든 다음 검색합니까? 이 방법의 성능과 간단한 for 루프를 비교해 볼 가치가 있다고 생각합니다. 특히 리소스가 제한된 모바일 플랫폼에서 실행중인 경우.
— Doug

7
@Doug 성능에 대한 요점은 맞지만 병목 현상이 발생할 때까지 IO / 네트워크에 거의 정의 된 응용 프로그램의 경우 한 줄의 코드를 7 개로 바꾸는 사람은 누구입니까?
— Jared Smith

6
기술적으로 축소 된 JS 파일은 한 줄도이며, D
— greaterKing

371

Array.prototype.findIndex 는 IE 이외의 모든 브라우저에서 지원됩니다 (에지 없음). 그러나 제공된 폴리 필 은 훌륭합니다.

var indexOfStevie = myArray.findIndex(i => i.hello === "stevie");

지도가있는 솔루션은 괜찮습니다. 그러나 모든 검색마다 전체 배열을 반복합니다. 일치하는 것이 발견되면 반복을 중지 하는 findIndex 의 최악의 경우입니다 .


간결한 방법은 없지만 (개발자가 IE8에 대해 걱정해야 할 때) 일반적인 해결책은 다음과 같습니다.

var searchTerm = "stevie",
    index = -1;
for(var i = 0, len = myArray.length; i < len; i++) {
    if (myArray[i].hello === searchTerm) {
        index = i;
        break;
    }
}

또는 기능으로 :

function arrayObjectIndexOf(myArray, searchTerm, property) {
    for(var i = 0, len = myArray.length; i < len; i++) {
        if (myArray[i][property] === searchTerm) return i;
    }
    return -1;
}
arrayObjectIndexOf(arr, "stevie", "hello"); // 1

몇 가지 참고 사항 :

  1. 배열에서 for ... in 루프를 사용하지 마십시오
  2. "바늘"을 찾은 후에는 루프에서 벗어나거나 기능에서 복귀하십시오.
  3. 객체 평등에주의

예를 들어

var a = {obj: 0};
var b = [a];
b.indexOf({obj: 0}); // -1 not found

이 함수는 searchTerm이어야하기 때문에 검색어 비교가 잘못되었습니다 :)
— Antonio Laguna

여러 번 발생했습니다
— Joe

3
@SteveBennett 성능 최적화 버전입니다. 배열의 길이는 한 번만 결정해야합니다 (for-loop의 변수가 초기화 될 때). 귀하의 경우, 길이는 새로 반복 될 때마다 확인됩니다. stackoverflow.com/questions/5349425/… 및 stackoverflow.com/questions/8452317/… 도 참조하십시오. 그러나 성능이 높지 않으면 실제로 중요하지 않습니다.
— loother

1
좋은 답변이지만 성능 벤치마킹 ( jsperf.com/find-index-of-object-in-array-by-contents 참조 )을 수행했으며 여기에 언급 된 함수 기반 답변이 두 번째로 가장 높은 답변 인 것으로 나타났습니다. 내 대답 에서 언급했듯이 더 성능이 좋은 유일한 것은 함수 대신 프로토 타입에 넣는 것 입니다.
— Uniphonic

123

ES2015에서 이것은 매우 쉽습니다.

myArray.map(x => x.hello).indexOf('stevie')

또는 더 큰 어레이의 성능이 더 좋을 수도 있습니다.

myArray.findIndex(x => x.hello === 'stevie')

2
ES6를 사용하는 좋은 접근 방법
— kag

내 대답에서 언급했듯이 이러한 방법 중 어느 것도 프로토 타입 for 루프만큼 성능이 우수하지 않다는 것에 놀랐습니다. findIndex 메소드 브라우저 지원이 약간 열악하지만 동일한 작업을 수행하는 것처럼 보이지만 여전히 성능이 떨어집니다. 벤치 마크에 대한 내 답변의 링크를 참조하십시오.
— Uniphonic

현재 수행중인 작업에 성능이 중요한지 알아야합니다. 내 경험으로는 거의 없지만 ymmv입니다.
— Steve Bennett

24
var idx = myArray.reduce( function( cur, val, index ){

    if( val.hello === "stevie" && cur === -1 ) {
        return index;
    }
    return cur;

}, -1 );

17

Pablo의 답변이 마음에 들지만 Array # indexOf 및 Array # map이 모든 브라우저에서 작동하지는 않습니다. Underscore는 사용 가능한 경우 기본 코드를 사용하지만 대체 기능도 있습니다. 또한 Pablo의 익명 맵 방법이하는 일을 정확하게 수행하기위한 퍽 방법이 있습니다.

var idx = _.chain(myArray).pluck("hello").indexOf("Stevie").value();

1
Array.prototype.map ()는 IE9 +에 대한 soported되고 당신은 IE8, 7, 6에 대한 Polyfill를 사용할 수 있습니다 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
— 요한 Echavarria

1
polyfill을 사용할 수 있습니다. . . 또는 밑줄이나 lodash를 사용할 수 있습니다. 기본적으로 다른 많은 것들이 붙어있는 polyfill입니다 . 밑줄에 대한 이의는 무엇입니까? 크기?
— tandrewnichols

나는 Underscore를 정말 좋아합니다. 당신의 대답은 영리하지만 IMHO Pablo의 대답은 가장 깨끗합니다.
— Johann Echavarria

와우 나는 그런 체인을 사용하지 않았다. 나는 그것이 검색을 유창하게 만드는 방법을 정말로 좋아한다.
— Dylan Pierce

chain여기서 불필요한 것입니다. _.pluck(myArray, 'hello').indexOf('stevie')
— Steve Bennett

14

또는 프로토 타입을 작성하십시오.

Array.prototype.indexOfObject = function arrayObjectIndexOf(property, value) {
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][property] === value) return i;
    }
    return -1;
}

myArr.indexOfObject("name", "stevie");

9
매우 편리합니다! exisitng Array.indexOf 메서드를 방해하지 않도록 prototype.indexOfObject를 선택하지만. Array.prototype.indexOfObject = function(property, value) { for (var i = 0, len = this.length; i < len; i++) { if (this[i][property] === value) return i; } return -1; };
— Adam

1
나는 이전 함수가 미리 저장되어있는 자체 실행 클로저로 래핑하고 대체 함수의 첫 번째 라인은의 라인을 따라 무언가를 감쌀 것입니다 if (typeof property === 'string' || typeof property === 'number' || typeof property === 'boolean') return oldIndexOf(property, value);. 이것은 불변의 몇 가지 유형이기 때문입니다. 또한 필요한 경우 기본 메소드로 대체 할 수 있도록 세 번째 인수를 사용합니다.
— Isiah Meadows

8

간결한

myArray.indexOf('stevie','hello')

사용 사례 :

  /*****NORMAL****/  
[2,4,5].indexOf(4) ;//OUTPUT 1
 /****COMPLEX*****/
 [{slm:2},{slm:4},{slm:5}].indexOf(4,'slm');//OUTPUT 1
 //OR
 [{slm:2},{slm:4},{slm:5}].indexOf(4,function(e,i){
   return e.slm;
});//OUTPUT 1
/***MORE Complex**/
[{slm:{salat:2}},{slm:{salat:4}},{slm:{salat:5}}].indexOf(4,function(e,i){
   return e.slm.salat;
});//OUTPUT 1

API :

    Array.prototype.indexOfOld=Array.prototype.indexOf

    Array.prototype.indexOf=function(e,fn){
      if(!fn){return this.indexOfOld(e)}
      else{ 
       if(typeof fn ==='string'){var att=fn;fn=function(e){return e[att];}}
        return this.map(fn).indexOfOld(e);
      }
    };

6

여기에서 다양한 답변에 대한 성능 테스트를 수행하여 누구나 스스로 실행할 수 있습니다.

https://jsperf.com/find-index-of-object-in-array-by-contents

Chrome에서 처음 테스트 한 결과, 프로토 타입 내부에서 for 루프 설정을 사용하는 다음 방법이 가장 빠릅니다.

Array.prototype.indexOfObject = function (property, value) {
    for (var i = 0, len = this.length; i < len; i++) {
        if (this[i][property] === value) return i;
    }
    return -1;
}

myArray.indexOfObject("hello", "stevie");

이 코드는 Nathan Zaetta의 답변을 약간 수정 한 것입니다.

성능 벤치 마크에서 대상은 1000 객체 배열의 중간 (인덱스 500)과 끝 (인덱스 999)에 있고 대상을 배열의 마지막 항목으로 넣더라도 (시도) 그것이 발견되기 전에 배열의 모든 단일 항목을 반복해야 함) 여전히 여전히 가장 빠릅니다.

이 솔루션은 또한 마지막 행만 반복하면되기 때문에 반복적으로 실행하기에 가장 간결한 장점 중 하나입니다.

myArray.indexOfObject("hello", "stevie");

2
나는 내 자신의 테스트와 함께 바이올린을 사용 하여이 질문에 대한 답변을 게시하려고했지만 답변 덕분에 더 이상 할 필요가 없습니다. 나는이 같은 결과에 도착하지만, 사용 - 난 그냥 테스트를 확인하려는 while대신 루프를 for하나하고 performance.now(). 나는이 응답을 더 upvoted 것을 원하는 것 그리고 내가 전에 그것을보고 있음을,이 ... 나에게 시간을 저장 한 것
— 음 Cognyto


5

여기에있는 대부분의 다른 답변은 유효합니다. 때로는 사용하는 곳 근처에서 짧고 간단한 기능을 만드는 것이 가장 좋습니다.

// indexOf wrapper for the list of objects
function indexOfbyKey(obj_list, key, value) {
    for (index in obj_list) {
        if (obj_list[index][key] === value) return index;
    }
    return -1;
}
// Find the string in the list (default -1)
var test1 = indexOfbyKey(object_list, 'name', 'Stevie');
var test2 = indexOfbyKey(object_list, 'last_name', 'some other name');

그것은 당신에게 중요한 것에 달려 있습니다. 코드 줄을 절약하고 하나의 라이너를 사용하거나 다양한 경우를 포괄하는 일반적인 솔루션을 사용하는 것이 매우 영리 할 수 ​​있습니다. 그러나 미래의 개발자들에게 추가적인 리버스 엔지니어링 작업을하는 것보다는 "여기서 이렇게 했어요"라고 말하는 것이 더 낫습니다. 특히 당신이 당신의 질문에서와 같이 자신을 "초보자"라고 생각한다면.


4
array.filter(function(item, indx, arr){ return(item.hello === 'stevie'); })[0];

마음 [0].

의 답변 reduce과 같이 사용 하는 것이 좋습니다 Antonio Laguna.

간결한 사과 ...


4

객체가 배열 내에서 사용하는 객체와 동일한 객체 인 경우 마치 문자열과 동일한 방식으로 객체의 인덱스를 얻을 수 있어야합니다.

var hello = {
    hello: 'world',
    foo: 'bar'
};
var qaz = {
    hello: 'stevie',
    foo: 'baz'
}

var qazCLONE = { // new object instance and same structure
    hello: 'stevie',
    foo: 'baz'
}

var myArray = [hello,qaz];

myArray.indexOf(qaz) // should return 1
myArray.indexOf(qazCLONE) // should return -1

이것은 IndexOf가 값과 일치하는지 또는 무엇인지 불확실했기 때문에 찾고있는 대답입니다. 이제 IndexOf를 사용하여 객체를 찾을 수 있으며 동일한 속성을 가진 다른 객체가 있는지 걱정할 필요가 없습니다.
— MDave



3

위치를 찾는 데 관심이 있다면 @ Pablo 's answer을 참조하십시오 .

pos = myArray.map(function(e) { return e.hello; }).indexOf('stevie');

그러나 요소 를 찾는 것을 기대하는 경우 (예 : 이와 같은 작업을 생각하는 myArray[pos]경우)을 사용하여 보다 효율적인 한 줄 방법이 있습니다 filter.

element = myArray.filter((e) => e.hello === 'stevie')[0];

성능 결과보기 (~ + 42 % ops / sec) : http://jsbench.github.io/#7fa01f89a5dc5cc3bee79abfde80cdb3


2

이 예를 참조하십시오 : http://jsfiddle.net/89C54/

for (i = 0; i < myArray.length; i++) {
    if (myArray[i].hello === 'stevie') {
        alert('position: ' + i);
        return;
    }
}

0으로 세기 시작합니다.


2

아래 코드를 확인하고 모든 객체에 작동하는 일반 기능을 만들었습니다.

function indexOfExt(list, item) {
    var len = list.length;

    for (var i = 0; i < len; i++) {
        var keys = Object.keys(list[i]);
        var flg = true;
        for (var j = 0; j < keys.length; j++) {
            var value = list[i][keys[j]];
            if (item[keys[j]] !== value) {
                flg = false;
            }
        }
        if (flg == true) {
            return i;
        }
    }
    return -1;
}

var items = [{ "hello": 'world', "foo": 'bar' }];
var selectedItem = { "hello": 'world', "foo": 'bar' };
alert(items.indexOf(selectedItem));
alert(indexOfExt(items, selectedItem));

첫 번째 경고는 -1 (평균 일치를 찾을 수 없음)을 반환하고 두 번째 경고는 0 (평균 일치를 찾았습니다)을 반환합니다.


2

underscore.js 라이브러리_.findIndex 에서 사용

여기 예가 있습니다 _.findIndex([{a:1},{a: 2,c:10},{a: 3}], {a:2,c:10}) //1


추가 라이브러리에서 메소드를 제안하는 경우 메소드의 출처를 언급해야합니다.
— Craicerjack

@Steve Bennett 라이브러리의 멋진 사용. 이제 lodash에 있음
— zabusa

2

lodash 또는 다른 라이브러리없이 ES6 findIndex메소드를 사용하여 다음을 작성할 수 있습니다.

function deepIndexOf(arr, obj) {
  return arr.findIndex(function (cur) {
    return Object.keys(obj).every(function (key) {
      return obj[key] === cur[key];
    });
  });
}

이것은 객체의 즉각적인 속성을 비교하지만 속성으로 재귀하지는 않습니다.

구현에서 findIndex아직 제공하지 않는 경우 (대부분은 제공 하지 않음)이 검색을 지원하는 라이트 폴리 필을 추가 ​​할 수 있습니다.

function deepIndexOf(arr, obj) {
  function findIndex = Array.prototype.findIndex || function (pred) {
    for (let i = 0; i < this.length; ++i) {
      if (pred.call(this, this[i], i)) {
        return i;
      }
    }

    return -1;
  }

  return findIndex.call(arr, function (cur) {
    return Object.keys(obj).every(function (key) {
      return obj[key] === cur[key];
    });
  });
}

( 이 속임수에 대한 나의 대답에서 )


2

기본적이고 편리한 기능을 Array.prototype.findIndex()기본적으로 사용할 수 있습니다 .

findIndex () 메소드는 배열의 요소가 제공된 테스트 기능을 만족하는 경우 배열의 색인을 리턴합니다. 그렇지 않으면 -1이 반환됩니다.

Internet Explorer, Opera 및 Safari에서는 지원되지 않지만 아래 링크에 제공된 Polyfill을 사용할 수 있습니다.

추가 정보:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

var hello = {
  hello: 'world',
  foo: 'bar'
};
var qaz = {
  hello: 'stevie',
  foo: 'baz'
}

var myArray = [];
myArray.push(hello, qaz);

var index = myArray.findIndex(function(element, index, array) {
  if (element.hello === 'stevie') {
    return true;
  }
});
alert('stevie is at index: ' + index);


2

의 Furthor @Monika Garg를 응답 , 당신은 사용할 수 있습니다 findIndex()(A가 polyfill unsupprted 브라우저가).

나는 사람들 이이 대답을 내리는 것을 보았고 나는 그들이 잘못된 구문 때문에이 작업을 수행하기를 희망합니다. 내 의견으로는 이것이 가장 우아한 방법이기 때문입니다.

findIndex () 메소드는 배열의 요소가 제공된 테스트 기능을 만족하는 경우 배열의 색인을 리턴합니다. 그렇지 않으면 -1이 반환됩니다.

예를 들면 다음과 같습니다.

var hello = {
  hello: 'world',
  foo: 'bar'
};
var qaz = {
  hello: 'stevie',
  foo: 'baz'
}

var myArray = [];
myArray.push(hello,qaz);

var index = myArray.findIndex(function(element) {
  return element.hello == 'stevie';
});

alert(index);


이 방법은 우아해 보이지만 MDN에 따르면 IE를 지원하지 않습니까? developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
— Jaakko Karhu

polyfill을 사용하십시오 (답변의 링크).
— Mosh Feu

1

이것이 배열에서 객체의 인덱스를 찾는 방법입니다

    var myArray = [{  hello: 'world',
        foo: 'bar'
    },{
        hello: 'stevie',
        foo: 'baz'
    }];



    for (i = 0; i < myArray.length; i++) {
        if (myArray[i].hello === 'stevie') {
            alert('position: ' + i);
            return;
        }
    }

0

이것은 사용자 정의 코드없이 작동합니다

var arr, a, found;
arr = [{x: 1, y: 2}];
a = {x: 1, y: 2};
found = JSON.stringify(arr).indexOf(JSON.stringify(a)) > - 1;
// found === true

참고 : 이것은 실제 색인을 제공하지 않으며 객체가 현재 데이터 구조에 존재하는지 알려줍니다.


1
이것은 인덱스를 얻을 수 없기 때문에 유효하지 않습니다
— Antonio Laguna

0

간단하게 사용할 수 있습니다

const someId = 2;
const array = [{id:1}, {id:2}, {id:3}];
const index = array.reduce((i, item, index) => item.id === someId ? index : i, -1);
alert('someId ' + someId + ' is at index ' + index);

밑줄도없고 줄임말입니다.


0
var hello = {hello: "world",  foo: "bar"};
var qaz = {hello: "stevie", foo: "baz"};
var myArray = [];
myArray.push(hello,qaz);

function indexOfObject( arr, key, value   ) {
    var j = -1;
    var result = arr.some(function(obj, i) { 
        j++;
        return obj[key] == value;
    })

    if (!result) {
        return -1;
    } else {
        return j;
    };
}

alert(indexOfObject(myArray,"hello","world"));

Array some method를 사용하십시오.
— user3235365


-2

findIndex()방법 을 사용하는 것을 선호합니다 .

 var index = myArray.findIndex('hello','stevie');

index 색인 번호를 알려줍니다.


1
답변, 맞춤법 및 코드 들여 쓰기 및 :)가 잘못 되었습니까?
— Sachin Verma

1
findIndex는 자바 스크립트 표준 구현에 없습니다. 그러한 방법에 대한 다가오는 (ecma 6) 제안이 있지만 서명은 그렇지 않습니다. 의미를 명확히하고 (메소드 이름 일 수도 있음) findIndex 메소드 선언을 지정하거나 사용중인 라이브러리 이름을 지정하십시오.
— Sebastien F.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.