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


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.