web-dev-qa-db-ja.com

条件に一致する、配列内のオブジェクトのインデックスを取得します

私はこのような配列を持っています:

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

配列全体を反復せずに、条件に一致するオブジェクトのインデックスを取得する方法を教えてください。

例えばprop2=="yutu"が与えられたとき、私はインデックス1を取得したいです。

.indexOf()は見ましたが、["a1","a2",...]のような単純な配列に使われていると思います。 $.grep()もチェックしましたが、これはインデックスではなくオブジェクトを返します。

217
amp

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);

Google 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');

ほとんどの最適化と同様に、これは慎重に適用する必要があり、実際に必要な場合にのみ適用します。

518
georg

どのようにしてオブジェクトのインデックスを取得することができますか(配列に沿って繰り返すことなく)。

できません、 something は(少なくとも1回)配列を反復処理する必要があります。

条件が大きく変わる場合は、ループしてその中のオブジェクトを調べて、条件に一致するかどうかを確認する必要があります。ただし、ES5機能を備えたシステム(またはシムをインストールした場合)では、その繰り返しはかなり簡潔に行えます。

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

これはnew(ish) Array#some関数 を使用します。これは、指定した関数がtrueを返すまで配列内のエントリをループします。私がそれに与えた関数は、一致するエントリのインデックスを保存し、そして反復を止めるためにtrueを返します。

もちろん、forループを使うだけです。あなたのさまざまな繰り返しオプションは この他の答え でカバーされています。

しかし、このルックアップに常に同じプロパティを使用する場合、およびプロパティ値が一意の場合は、1回だけループしてそれらをマッピングするオブジェクトを作成できます。

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

(または、forループまたは その他のオプション のいずれかを使用することもできます。)

prop2 = "yutu"でエントリを見つける必要があるなら、あなたはこれをすることができます:

var entry = prop2map["yutu"];

これを「クロスインデックス」と呼びます。当然、エントリを削除または追加(またはそれらのprop2値を変更)した場合は、マッピングオブジェクトも更新する必要があります。

24
T.J. Crowder

TJ Crowderが言ったことは、 lodash を使うと、常に何らかの隠れた繰り返しがあることになります。

var index = _.findIndex(array, {prop2: 'yutu'})
20
aliak
var index;
yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' ? (index = i, true) : false;
});

配列のすべての要素を繰り返します。インデックスとtrueまたは条件が一致しない場合はfalseを返します。

重要なのは、明示的なtrueの戻り値(またはbooleanの結果がtrueの値)です。 0(ブール(0)=== false)の可能なインデックスのため、単一の割り当てでは十分ではありません。これはエラーにはなりませんが、反復の中断を無効にします。

編集する

上記のより短いバージョン:

yourArray.some(function (elem, i) {
    return elem.prop2 === 'yutu' && ~(index = i);
});
11
Nina Scholz
var CarId = 23;

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

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
3
GibboK

正確に反復したくないのはなぜですか。新しい Array.prototype.forEach はこの目的のために素晴らしいです!

必要に応じて、バイナリ検索ツリーを使用して単一のメソッド呼び出しで検索できます。これはJSのBTreeとRed black Searchツリーのきちんとした実装です - https://github.com/vadimg/js_bintrees - しかし、同時にインデックスを見つけることができるかどうかはわかりません。

1
Rishabh
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
pranabesh chand

Array.reduce()を使用した1ステップ - 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を返します。

1
SagiSergeNadir

私は上記で多くの解決策を見ました。

ここでは、配列オブジェクト内の検索テキストのインデックスを見つけるために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)
1

コードを最適化する:

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

なぜ彼らは皆真と偽を返しているのです。

0
Durgpal Singh
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の回避策です。

もう1つのエレガントな方法があります。

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

同時に強調したいのですが、Array.someはバイナリまたは他の効率的な検索手法で実装することができます。そのため、ブラウザによってはforループよりもパフォーマンスが向上する可能性があります。

0
Sanjoy