JavaScriptオブジェクトの配列内のIDでオブジェクトを検索します


1546

私は配列を持っています:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]

配列の構造を変更できません。idが渡されており、配列内のそのオブジェクト45を取得'bar'したいと考えています。

JavaScriptまたはjQueryでこれを行うにはどうすればよいですか?

回答:


1190

次のfind()方法を使用します。

myArray.find(x => x.id === '45').foo;

MDNから:

このfind()メソッドは、配列の要素が指定されたテスト関数を満たす場合、配列の最初の値を返します。それ以外の場合undefinedは返されます。


代わりにそのインデックスを検索する場合は、次を使用しますfindIndex()

myArray.findIndex(x => x.id === '45');

MDNから:

このfindIndex()メソッドは、指定されたテスト関数を満たす配列の最初の要素のインデックスを返します。それ以外の場合は-1が返されます。


一致する要素の配列を取得する場合は、filter()代わりにメソッドを使用します。

myArray.filter(x => x.id === '45');

これはオブジェクトの配列を返します。fooプロパティの配列を取得したい場合は、次のmap()メソッドを使用してこれを行うことができます。

myArray.filter(x => x.id === '45').map(x => x.foo);

サイドノート:のようなメソッドfind()またはfilter()、そして矢印の機能は、ので、あなたはこれらのブラウザをサポートしたい場合は、あなたが使用してコードtranspileなければならない、(IEのような)古いブラウザでサポートされていないバベル(とポリフィルを)。


2
したがって、複数のテスト条件の場合は、myArray.find(x => x.id === '45' && x.color == 'red')。foo
Apqu

2
私にとって、これまでのところ最良の答えです。jQueryも、新しい補助配列を作成する必要もありません。
Canta 2017年

myArray.find(x => x.id === '45')Mac PCでは機能しません
Govinda Rajbhar

@TJCrowder MDNからコードにポリフィルをコピーアンドペーストするのは良い考えではないと思います。代わりに、ポリフィル付きのnpmパッケージを使用する必要があります。そして、Babelには、ES2015 +機能のポリフィルが babel-polyfillパッケージに含めています。
のMichałPerłakowski

2
myArray.find(x => x.id === '45')。foo; IDが「45」のオブジェクトがない場合は、例外をスローします。
Frazer Kirkman

1466

すでにjQueryを使用しているため、配列を検索するためのgrep関数を使用できます。

var result = $.grep(myArray, function(e){ return e.id == id; });

結果は、見つかった項目の配列です。オブジェクトが常に存在し、1回だけ発生することがわかっている場合は、を使用result[0].fooして値を取得できます。それ以外の場合は、結果の配列の長さを確認する必要があります。例:

if (result.length === 0) {
  // no result found
} else if (result.length === 1) {
  // property found, access the foo property using result[0].foo
} else {
  // multiple items found
}

124
JavaScriptの演算子の奇妙な問題を回避する===には==、の代わりに使用する方が安全==です。
Vicky Chijwani

11
@VickyChijwani:文字列を文字列と比較するときに問題はありますか?
Guffa

38
あなたがしている場合まあ、絶対に両方のことを確認してくださいe.idid文字列になり、私が使用することのOKを想定します==。あなたがわからない場合は(以降しかし、あなたが問題に直面するかもしれない'' == 0ですtrueが、'' === 0ありますfalse)。言うまでもなく===、高速であるようです(stackoverflow.com/questions/359494/…)。
Vicky Chijwani

101
他のプログラミング言語とまったく同じように===機能するため、基本的には常に使用します。JavaScriptには存在しないと思います。====
Vicky Chijwani

6
@de。ここでの多くの回答は、一意の値を検索するときに意図された動作を提供します。本質的には、ループが早期に戻るかループから脱落する(または下位レベルの構成に反復を停止するように指示する)ことによって、それらを認識することができます。標準的な例についてはJaredParの回答を、同じ洞察についてはその回答に関するAaroniusのコメントを参照してください。一般に、人々はこのように「フィルター」と「検索」機能を区別しますが、用語は異なります。より効率的ですが、これは依然として線形検索であるため、ハッシュテーブルを使用する場合は、Aaron Digullaの回答を参照してください(詳細に注意してください)。
2014年

362

別の解決策は、ルックアップオブジェクトを作成することです。

var lookup = {};
for (var i = 0, len = array.length; i < len; i++) {
    lookup[array[i].id] = array[i];
}

... now you can use lookup[id]...

これは、多くの検索を行う必要がある場合に特に興味深いものです。

IDとオブジェクトが共有されるため、これはより多くのメモリを必要としません。


6
まさに私が探していたもの。毎回ループして、CouchDBから受信したデータを変更して自分に役立つフォーマットに変換するだけでよいときに、リストから各項目を削除して、複雑にしすぎていたのがおかしいニーズ。+1サー!
スリックプレイド2013

5
これは賢いです。用途ごとにアレイ全体を見渡して他の人がどのように確信していたかは想像できません。
Aladdin Mhemed 2013

4
限り、あなたはプロパティの順序に依存しないよう:stackoverflow.com/questions/4886314/...
Marle1

休憩中です。検索するオブジェクトが1つしかないことがわかっている場合は、ループ内で良いオプション/改善を行いますか?
irJvV 2015

7
@irJvV:いいえ、それはまったく意味がありません。上記のコードは、多くの検索を行う必要がある場合に役立ちます。一度だけ見ると、lookupオブジェクトの作成は時間の無駄です。
アーロンディグラ

174

ECMAScript 2015は、配列に対してfind()メソッドを提供します。

var myArray = [
 {id:1, name:"bob"},
 {id:2, name:"dan"},
 {id:3, name:"barb"},
]

// grab the Array item which matchs the id "2"
var item = myArray.find(item => item.id === 2);

// print
console.log(item.name);

外部ライブラリなしで動作します。ただし、古いブラウザのサポートが必要な場合は、このポリフィルを含めることができます。


1
多分それはまだ非常に実験的であるように思われ、多くのブラウザがそれをサポートしないので、 developer.mozilla.org
en

2
これはに簡略化できますmyArray.find(d=>d.id===45).foo;
Shaggy

1
@ShaggyまたはmyArray.find(({ id }) => id === 45).foo。しかし、これはES2015構文が現在と同様にサポートされる前に書かれた古い回答です。@Gothdoの答えは現在、スレッド内で最新のものです。
ルナー・バーグ

1
@Shaggy .find()が未定義を返す場合、最適化はエラーをスローします。したがって、このソリューションは、一致が保証されている場合にのみ使用できます。
Herbert Peters

1
@HerbertPetersあなたはあなたが本当に簡単になり、ヌルチェック、なかれできることを確認したい場合は、オプションのチェーンをmyArray.find(d => d.id === 45)?.foo
ルナー・バーグ

141

Underscore.jsには、そのための優れたメソッドがあります。

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })

42
記録としては、Lo-Dash(アンダースコアよりも明らかにパフォーマンスが高いことが多い)にも同様の方法があります。ここのドキュメント:lodash.com/docs#find
user456584

1つのオブジェクトのみが必要な場合は、findWhereを使用すると、1つの結果が見つかった後は検索が続行されないため、より効率的です。
Foreever

@Foreever _.findのドキュメントから:「関数は、受け入れ可能な要素が見つかるとすぐに戻り、リスト全体を走査しません。」
GijsjanB

129

最も簡単な方法は次のようになると思いますが、Internet Explorer 8(またはそれ以前)では機能しません。

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property

私は好奇心が強いですが、通常と比較してここにパフォーマンス上の利点はありますforか?
Igor Zinov'yev

@Igor Zinov'yev:はい、これらのES5アレイツールを使用すると、確かにパフォーマンスに影響があります。要素ごとに個別の関数が実行されるため、直接forループに比べて高速ではありません。
pimvdb 2011

それであなたはそれが遅くなると言っているのですか?また、forループは常に最初の一致で終了するのに対し、私が見る限り、常に配列全体をスキャンします。
Igor Zinov'yev

あなたがIE8のサポートが必要な場合は、ただでこれをドロップします。stackoverflow.com/questions/7153470/...
アダム・グラント

要素がない場合、このコードはエラーをスローしますid
Stan

71

以下をお試しください

function findById(source, id) {
  for (var i = 0; i < source.length; i++) {
    if (source[i].id === id) {
      return source[i];
    }
  }
  throw "Couldn't find object with id: " + id;
}

17
これはそれ自体の答えには値しませんでしたが、最新のブラウザでは、このソリューションは次のように書くことができます:jsfiddle.net/rwaldron/j3vST
Rick

12
効率を上げる場合は、filter()を使用するよりもこの例の方が高速であることに注意してください(Rickの例を参照)。これは、最初に一致する項目が見つかると戻り、filter()は、一致。これには、追加の配列を作成したり、各アイテムの関数を呼び出したりするコストもかかりません。
Aaronius 2013

3
@Rick、その答えについて最も興味深いことは明らかに、jsFiddleの出力ウィンドウにfirebugコンソールを追加できることです。これは、ログを記録して他の人にコンソールを開いて出力を表示するように指示するよりもはるかに優れています。驚くばかり!
KyleMit 14

1
これまで誰も言及していないので、AngularJSにもフィルターメソッドがあることを付け加えたいと思います。
2015



31

上記のfindById関数の一般的でより柔軟なバージョン:

// array = [{key:value},{key:value}]
function objectFindByKey(array, key, value) {
    for (var i = 0; i < array.length; i++) {
        if (array[i][key] === value) {
            return array[i];
        }
    }
    return null;
}

var array = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
var result_obj = objectFindByKey(array, 'id', '45');

15

これは、map()関数を使用して簡単に取得できます。

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var found = $.map(myArray, function(val) {
    return val.id == 45 ? val.foo : null;
});

//found[0] == "bar";

作業例:http : //jsfiddle.net/hunter/Pxaua/


1
jQueryがmap自動的にnull要素を削除するという事実を忘れていました。map結果は元のコレクションと同じ長さではないため、私との一般的な概念に誤解を招くように思えます。
MaxArt

14

フィルターを使用できます

  function getById(id, myArray) {
    return myArray.filter(function(obj) {
      if(obj.id == id) {
        return obj 
      }
    })[0]
  }

get_my_obj = getById(73, myArray);

1
@TobiasBeuving-Array.find()を使用するものもプレーンJSであり、最初の検索で停止するので、より効率的です。
エイドリアンリンチ

12

ここには多くの正しい答えがありますが、それらの多くは、これを2回以上行うと不必要にコストのかかる操作であるという事実に対処していません。極端な場合には、これが実際のパフォーマンスの問題の原因になる可能性があります。

現実の世界では、多くのアイテムを処理していてパフォーマンスが懸念される場合は、最初にルックアップを作成する方がはるかに高速です。

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

その後、次のような一定の時間にアイテムを取得できます。

var bar = o[id];

ルックアップとして、オブジェクトの代わりにマップを使用することも検討してくださいhttps : //developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map


11

ネイティブを使用する Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

見つかった場合はオブジェクト要素を返し、見つからない場合は false


注:Array.reduceはIE8以前ではサポートされていません。
Burn_E99 2016年

7

これを複数回行う場合は、マップ(ES6)を設定できます。

const map = new Map( myArray.map(el => [el.id, el]) );

次に、単に行うことができます:

map.get(27).foo

6

これは、純粋なJavaScriptでそれを実行する方法です。ECMAScript3以降で機能することを考えることができる最小限の方法で。一致が見つかるとすぐに戻ります。

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'

5

より一般的で短い

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

あなたの場合Ex。var element = findFromArray(myArray,'id',45)要素全体が得られます。


4

http://sugarjs.com/からSugarjsを試すことができます。

Arraysには非常に優れたメソッドがあり.findます。したがって、次のような要素を見つけることができます。

array.find( {id: 75} );

さらに多くのプロパティを持つオブジェクトをそれに渡して、別の「where-clause」を追加することもできます。

Sugarjsはネイティブオブジェクトを拡張し、一部の人々はこれを非常に悪いと考えています...


2
新しいEcmaScriptバージョンが同じ名前の新しいメソッドを導入する可能性があるので、それ悪です。そして、何が起こったのfindか、これが正確に何が起こったのかを推測ます。私の提案は、ネイティブプロトタイプを拡張する場合は、常により具体的な名前を使用し、最も単純なものは将来の標準開発に任せることです。
MaxArt、2014

このコメントは2年近く前のものであり、今日はとにかくlodashを使用したいと思います。ただし、必要に応じて、sugajsのWebサイトでこのトピックについて読むことができます。彼らはあなたの意見に良い立場をとっています:sugarjs.com/native
deepflame

1
opは具体的にはjavascriptまたはjqueryソリューションを求めていました
Tobias Beuving

4

受け入れられた答えに基づいて構築:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

またはCoffeeScript:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo


3

配列内の任意のアイテムを反復します。アクセスするすべてのアイテムについて、そのアイテムのIDを確認します。一致する場合は、それを返します。

codezが必要な場合:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

そして、ECMAScript 5の配列メソッドを使用して同じこと:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}

3

ブラウザがECMA-262第5版(2009年12月)をサポートしている限り、これは機能し、ほぼ1行です:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});

2
ほとんど。要素が必要な条件を満たす場合にbFoundのみブール値になりtrueます。
MaxArt

3

配列に対して組み込みの「フィルター」関数を使用することにより、純粋なJavaScriptでもこれを行うことができます。

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}

したがって、単にの代わりに「id」を渡し、の代わりにkey「45」を渡すvalueと、45のidに一致する完全なオブジェクトが取得されます。つまり、

myArr.filterObjects("id", "45");

16
所有していないオブジェクトは変更しないでください。
のMichałPerłakowski

3

Array.prototype.filter()関数を使用します。

デモhttps : //jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON

var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];

フィルタ

var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}

ネストされたオブジェクト内を検索するにはどうすればよいですか?pets = falseと同様に、2つのオブジェクトを返します。
Valay

ネストされたループで.filterメソッドを使用しobj.infoます。 var getPerson = function(name){ return jsonObj.filter(function(obj) { return obj.info.filter(function(info) { return pets === false; }); }); }
Sumit Ridhal 2017年

es6スタイルも使用できますimo ... const filterData = jsonObj.filter(obj => obj.name === 'Alex')
DagicCross

3

Jqueryメソッドを使用できます $.each()/$.grep()

var data= [];
$.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}

または

var data = $.grep(array, function( n, i ) {
  return ( n !== 5 && i > 4 );
});

ES6構文を使用します。

Array.find, Array.filter, Array.forEach, Array.map

または使用Lodash https://lodash.com/docs/4.17.10#filter、アンダースコアhttps://underscorejs.org/#filter


2

Aaron Digullaが提供する答えは本当に気に入りましたが、後で繰り返し処理できるようにオブジェクトの配列を保持する必要がありました。だから私はそれを

	var indexer = {};
	for (var i = 0; i < array.length; i++) {
	    indexer[array[i].id] = parseInt(i);
	}
	
	//Then you can access object properties in your array using 
	array[indexer[id]].property


配列内の項目を見つけるために最速と同じソリューションを使用しました。しかし、parseIntはここでは冗長です。
aleha 2016

1

使用する:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

IDでオブジェクトを返す必要があります。


return obj.id === 5?obj:false; $ .eachを配列の反復処理に多く使用しています。
マルセル2014

@marcel:うまくいきません。falseを返すとループが終了するため、オブジェクトが配列の最初の項目である場合にのみオブジェクトを見つけます。
Guffa

1

このソリューションも役立ちます。

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

私はそれを同じように$.grepして、1つのオブジェクトが見つかると、関数は配列ではなくオブジェクトを返します。


2
所有していないオブジェクトは変更しないでください。
のMichałPerłakowski

@Gothdo同意する。知らない人はfunction will return the object, rather than an array間違いをするかもしれませんが、それはユーザー次第だと思います。
soytian 2016

0

aggatonの答えから始めて、これはnullarraycallback「正しい」要素の真の値を返す関数が与えられた場合、実際に必要な要素を(または見つからない場合)返す関数です。

function findElement(array, callback) {
    var elem;
    return array.some(function(e) {
        if (callback(e)) {
            elem = e;
            return true;
        }
    }) ? elem : null;
});

これはIE8ではサポートされていないため、ネイティブでは機能しないことに注意してくださいsome。ポリフィルを提供することもできますが、代わりに常にクラシックforループがあります。

function findElement(array, callback) {
    for (var i = 0; i < array.length; i++)
        if (callback(array[i])) return array[i];
    return null;
});

実際には、より高速でコンパクトです。しかし、ホイールを作り直したくない場合は、アンダースコアやロダッシュなどのユーティリティライブラリを使用することをお勧めします。


0

最短、

var theAnswerObj = _.findWhere(array, {id : 42});

1
これには、アンダースコアライブラリを使用する必要があり、OPはプレーンなJavaScriptまたはjQueryソリューションを求めていました
Tobias Beuving

2
下線を含めたら、これは簡単な答えではありません!
Tim Ogilvy

-1

「axesOptions」は、オブジェクト形式が{:field_type => 2、:fields => [1,3,4]}であるオブジェクトの配列であると考えてください

function getFieldOptions(axesOptions,choice){
  var fields=[]
  axesOptions.each(function(item){
    if(item.field_type == choice)
        fields= hashToArray(item.fields)
  });
  return fields;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.