조건과 일치하는 배열 내 객체의 인덱스를 가져옵니다.


322

다음과 같은 배열이 있습니다.

[{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"},...]

전체 배열을 반복하지 않고 조건과 일치하는 객체의 인덱스를 어떻게 얻을 수 있습니까?

예를 들어, 주어진 prop2=="yutu"index을 얻고 싶습니다 1.

나는 그것을 보았지만 .indexOf()같은 간단한 배열에 사용된다고 생각합니다 ["a1","a2",...]. 또한 확인 $.grep()했지만 인덱스가 아닌 객체를 반환합니다.

답변:


733

2016 년 기준으로 Array.findIndex(ES2015 / ES6 표준) 을 사용해야 합니다.

a = [
  {prop1:"abc",prop2:"qwe"},
  {prop1:"bnmb",prop2:"yutu"},
  {prop1:"zxvz",prop2:"qwrq"}];
    
index = a.findIndex(x => x.prop2 ==="yutu");

console.log(index);

Chrome, Firefox 및 Edge에서 지원됩니다. Internet Explorer의 경우 링크 된 페이지에 폴리 필이 있습니다.

성능 메모

함수 호출은 비싸므로 실제로 큰 배열을 사용하면 간단한 루프가 다음보다 훨씬 잘 수행됩니다 findIndex.

let test = [];

for (let i = 0; i < 1e6; i++)
    test.push({prop: i});


let search = test.length - 1;
let count = 100;

console.time('findIndex/predefined function');
    let fn = obj => obj.prop === search;

    for (let i = 0; i < count; i++)
        test.findIndex(fn);
console.timeEnd('findIndex/predefined function');


console.time('findIndex/dynamic function');
    for (let i = 0; i < count; i++)
        test.findIndex(obj => obj.prop === search);
console.timeEnd('findIndex/dynamic function');


console.time('loop');
    for (let i = 0; i < count; i++) {
        for (let index = 0; index < test.length; index++) {
            if (test[index].prop === search) {
                break;
            }
        }
    }
console.timeEnd('loop');

대부분의 최적화와 마찬가지로 실제로 필요할 때만주의해서 적용해야합니다.


3
여기에 임시 배열이 필요하지 않습니다. 반복자 함수가 컨텍스트를 닫고 변수를 사용한다는 사실을 사용하십시오. 또한 비 jQuery 버전이 작동하지 않습니다 (색인 0?에 있다고 가정하십시오 ). 솔루션 모두 필요한 것보다 더 많은 반복을 수행합니다. 배열이 클 경우 이상적이지 않습니다 (검색이 많이 발생하지 않는 한 사람이 너무 클 가능성은 낮지 만 ).
TJ Crowder

@ thg435 : 여전히 간단한 레버가 트릭을 수행하는 Rube Goldberg 기계라고 생각합니다. :-) 그러나 이봐, 작동한다!
TJ Crowder

4
x => x.prop2=="yutu"findIndex () 작동 방식을 설명해 주 시겠습니까?
Abhay Pai

5
@AbhayPai : 그것은 동일합니다function(x) { return x.prop2=="yutu" }
georg

6
나는 polyfill을 사용하라는 제안을 좋아합니다. 그러나 화살표 / 람다 함수를 사용하기 때문에 polyfill을 사용하더라도 IE11에서 작성된 코드는 여전히 실패합니다. 로 재 작성 index = a.findIndex(function (x) { return x.prop2 == "yutu" })polyfill 코드, findIndex는 IE11에서 작동되도록 문제를 해결
릭 글로스를

26

배열을 따라 반복하지 않고 조건과 일치하는 객체의 인덱스를 어떻게 얻을 수 있습니까?

당신은 무언가 를 배열을 통해 반복해야합니다 (적어도 한 번).

조건이 많이 바뀌면 반복해서 객체를 살펴보고 조건과 일치하는지 확인해야합니다. 그러나 ES5 기능이있는 시스템 (또는 shim을 설치 한 경우)에서 해당 반복을 상당히 간결하게 수행 할 수 있습니다.

var index;
yourArray.some(function(entry, i) {
    if (entry.prop2 == "yutu") {
        index = i;
        return true;
    }
});

new (ish) Array#some함수를 사용합니다. 이 함수는 사용자가 제공 한 함수가 true를 반환 할 때까지 배열의 항목을 반복합니다. 내가 제공 한 함수는 일치하는 항목의 색인을 저장 한 다음 true반복을 중지하기 위해 반환 합니다.

또는 물론 for루프를 사용하십시오 . 다양한 반복 옵션은 이 다른 답변 에서 다룹니다 .

그러나이 조회에 항상 동일한 속성을 사용하려는 경우 속성 값이 고유 한 경우 한 번만 반복하고 객체를 만들어 매핑 할 수 있습니다.

var prop2map = {};
yourArray.forEach(function(entry) {
    prop2map[entry.prop2] = entry;
});

또는 다시 for루프 또는 다른 옵션을 사용할 수 있습니다 .

그런 다음로 항목을 찾아야 할 경우 다음 prop2 = "yutu"을 수행 할 수 있습니다.

var entry = prop2map["yutu"];

나는 이것을 "교차 색인"이라고 부른다. 당연히 항목을 제거하거나 추가하거나 prop2값을 변경하는 경우 매핑 개체도 업데이트해야합니다.


설명 주셔서 감사합니다! jQuery가 지적한 솔루션은 thg435내가 원하는 것을 해냈습니다.
amp

21

TJ Crowder가 말한 바와 같이, 매번 어떤 종류의 숨겨진 반복이있을 것입니다 .

var index = _.findIndex(array, {prop2: 'yutu'})

1
그냥 다양한 방법을 통해 루프 인덱스를 얻을 수있는 반면, 인덱스도 기본 배열 방법에 ES6 년에 채택 된 최고의 솔루션을 찾을
켈리 밀리

13
var CarId = 23;

//x.VehicleId property to match in the object array
var carIndex = CarsList.map(function (x) { return x.VehicleId; }).indexOf(CarId);

기본 배열 번호의 경우 다음을 수행 할 수도 있습니다.

var numberList = [100,200,300,400,500];
var index = numberList.indexOf(200); // 1

배열에서 값을 찾을 수 없으면 -1을 얻습니다.


11
var index;
yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' ? (index = i, true) : false;
});

배열의 모든 요소를 ​​반복합니다. 조건이 일치하지 않으면 인덱스와 true 또는 false를 반환합니다.

중요한 것은 명시적인 반환 값 true 또는 부울 결과가 true 인 값입니다. 0 (Boolean (0) === false)의 가능한 인덱스로 인해 단일 할당으로는 충분하지 않으므로 오류는 발생하지 않지만 반복 중단은 비활성화됩니다.

편집하다

위의 더 짧은 버전 :

yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' && ~(index = i);
});

두 번째 스 니펫에서 ~ 문자는 무엇을합니까?
serkan

@serkan, 그것은 비트 NOT| 연산자이며, 인덱스가 존재하는 경우 인덱스 (-1로)에서 진실 / 허위 결과 를 얻는 짧은 버전입니다 .
Nina Scholz

고마워 Nina, ~ 문자가 없으면 코드가 그대로 작동합니까?
serkan

@serkan, 귀하의 질문은 분명 ~하지 않지만 그것이 없으면 그렇게 작동하지 않습니다.
Nina Scholz

1
아, !!(index = 0)그리고 !!~(index = 0)실제로 차이. 감사!
serkan

4

Array.prototype.some () 을 다음과 같은 방법으로 사용할 수 있습니다 ( 다른 답변에서 언급 한 바와 같이).

https://jsfiddle.net/h1d69exj/2/

function findIndexInData(data, property, value) {
    var result = -1;
    data.some(function (item, i) {
        if (item[property] === value) {
            result = i;
            return true;
        }
    });
    return result;
}
var data = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]



alert(findIndexInData(data, 'prop2', "yutu")); // shows index of 1

4

위의 많은 솔루션을 보았습니다.

여기서는 map 함수를 사용하여 배열 객체에서 검색 텍스트의 색인을 찾습니다.

학생 데이터를 사용하여 답변을 설명하려고합니다.

  • 1 단계 : 학생들을위한 배열 객체를 만듭니다 (선택 사항은 자신의 배열 객체를 만들 수 있습니다).
    var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

  • 2 단계 : 텍스트를 검색 할 변수 만들기
    var studentNameToSearch = "Divya";

  • 3 단계 : 일치하는 인덱스를 저장할 변수를 만듭니다 (여기서는 map 함수를 사용하여 반복합니다).
    var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

var students = [{name:"Rambabu",htno:"1245"},{name:"Divya",htno:"1246"},{name:"poojitha",htno:"1247"},{name:"magitha",htno:"1248"}];

var studentNameToSearch = "Divya";

var matchedIndex = students.map(function (obj) { return obj.name; }).indexOf(studentNameToSearch);

console.log(matchedIndex);

alert("Your search name index in array is:"+matchedIndex)


3
function findIndexByKeyValue(_array, key, value) {
    for (var i = 0; i < _array.length; i++) { 
        if (_array[i][key] == value) {
            return i;
        }
    }
    return -1;
}
var a = [
    {prop1:"abc",prop2:"qwe"},
    {prop1:"bnmb",prop2:"yutu"},
    {prop1:"zxvz",prop2:"qwrq"}];
var index = findIndexByKeyValue(a, 'prop2', 'yutu');
console.log(index);

1

왜 정확하게 반복하고 싶지 않습니까? 새로운 Array.prototype.forEach 는이 목적에 적합합니다!

원하는 경우 이진 검색 트리를 사용하여 단일 메소드 호출을 통해 찾을 수 있습니다. 이것은 JS의 BTree 및 Red black Search 트리 ( https://github.com/vadimg/js_bintrees )의 깔끔한 구현 이지만 동시에 인덱스를 찾을 수 있는지 확실하지 않습니다.


1

Array.reduce ()를 사용하는 한 단계-jQuery 없음

var items = [{id: 331}, {id: 220}, {id: 872}];

var searchIndexForId = 220;
var index = items.reduce(function(searchIndex, item, index){
  if(item.id === searchIndexForId) { 
    console.log('found!');
    searchIndex = index;
  }
  return searchIndex;
}, null);

null색인을 찾지 못하면를 반환 합니다.


0
var list =  [
                {prop1:"abc",prop2:"qwe"},
                {prop1:"bnmb",prop2:"yutu"},
                {prop1:"zxvz",prop2:"qwrq"}
            ];

var findProp = p => {
    var index = -1;
    $.each(list, (i, o) => {
        if(o.prop2 == p) {
            index = i;
            return false; // break
        }
    });
    return index; // -1 == not found, else == index
}

0

Georg는 이미 ES6에 Array.findIndex가 있다고 언급했습니다. 그리고 다른 답변은 Array.some 메서드를 사용하는 ES5에 대한 해결 방법입니다.

하나 더 우아한 접근법은

var index;
for(index = yourArray.length; index-- > 0 && yourArray[index].prop2 !== "yutu";);

동시에 강조하고 싶습니다. Array.some은 이진 또는 다른 효율적인 검색 기술로 구현 될 수 있습니다. 따라서 일부 브라우저에서는 for 루프보다 성능이 우수 할 수 있습니다.


0

이 코드를 사용해보십시오

var x = [{prop1:"abc",prop2:"qwe"},{prop1:"bnmb",prop2:"yutu"},{prop1:"zxvz",prop2:"qwrq"}]
let index = x.findIndex(x => x.prop1 === 'zxvz')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.