web-dev-qa-db-ja.com

Javascriptで多次元オブジェクト/配列の値を見つける方法は?

私は多次元オブジェクトを持っています(基本的には配列です):

Object = {
   1 : { name : bob , dinner : pizza },
   2 : { name : john , dinner : sushi },
   3 : { name : larry, dinner : hummus }
}

キーが「夕食」であるオブジェクト/配列を検索し、「寿司」と一致するかどうかを確認できるようにしたいと思います。

JQueryには$ .inArrayがありますが、多次元配列では機能しないようです。または多分私は間違っています。 indexOfも1つの配列レベルでのみ機能するようです。

この機能や既存のコードはありませんか?

81
Questioner

次のような配列がある場合

var people = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

Arrayオブジェクトの filter メソッドを使用できます。

people.filter(function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]

新しいJavaScript実装では、関数式を使用できます。

people.filter(p => p.dinner == "sushi")
  // => [{ "name": "john", "dinner": "sushi" }]

map を使用して、"dinner": "sushi"を持っている人を検索できます。

people.map(function (person) {
  if (person.dinner == "sushi") {
    return person
  } else {
    return null
  }
}); // => [null, { "name": "john", "dinner": "sushi" }, null]

または reduce

people.reduce(function (sushiPeople, person) {
  if (person.dinner == "sushi") {
    return sushiPeople.concat(person);
  } else {
    return sushiPeople
  }
}, []); // => [{ "name": "john", "dinner": "sushi" }]

これを任意のキーと値に一般化できると確信しています!

184
adamse

jQueryには組み込みメソッド jQuery.grep があります。これは @ adamse's Answer のES5 filter関数と同様に機能し、古いブラウザーでは正常に機能するはずです。

Adamseの例を使用:

var peoples = [
  { "name": "bob", "dinner": "pizza" },
  { "name": "john", "dinner": "sushi" },
  { "name": "larry", "dinner": "hummus" }
];

次のことができます

jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
  // => [{ "name": "john", "dinner": "sushi" }]
17
Zach Lysobey

この検索を頻繁に行う場合は、実際に夕食が重要になるようにオブジェクトの形式を変更することを検討してください。これは、データベーステーブルでクラスター化されたプライマリキーを割り当てるようなものです。したがって、たとえば:

Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }

次のように簡単にアクセスできます:Object['sushi']['name']

または、オブジェクトが本当に単純な場合(オブジェクト内の「名前」)、次のように変更できます。

Obj = { 'pizza' : 'bob', 'sushi' : 'john' }

そして、Object['sushi']のようにアクセスします。

このようにデータオブジェクトを再構築することは、必ずしも常に可能であるとは限らないことは明らかですが、重要なことは、データオブジェクトが最適な方法で構造化されているかどうかを検討することです。このようなキーを作成すると、より速く、よりクリーンなコードを作成できます。

10
dallin
var getKeyByDinner = function(obj, dinner) {
    var returnKey = -1;

    $.each(obj, function(key, info) {
        if (info.dinner == dinner) {
           returnKey = key;
           return false; 
        };   
    });

    return returnKey;       

}

jsFiddle

-1が有効なキーでない限り。

8
alex

Alasql libraryを使用して、配列内のオブジェクトを見つけることができます。

var data = [ { name : "bob" , dinner : "pizza" }, { name : "john" , dinner : "sushi" },
     { name : "larry", dinner : "hummus" } ];

var res = alasql('SELECT * FROM ? WHERE dinner="sushi"',[data]);

この例を試してください jsFiddle

3
agershun

単純なforループを使用できます。

for (prop in Obj){
    if (Obj[prop]['dinner'] === 'sushi'){

        // Do stuff with found object. E.g. put it into an array:
        arrFoo.Push(Obj[prop]);
    }
}

次のフィドルの例は、dinner:sushiを含むすべてのオブジェクトを配列に入れます。

https://jsfiddle.net/3asvkLn6/1/

1
Rotareti

ここにはすでに多くの良い答えがありますので、もう1つではなく、lodashやアンダースコアのようなライブラリを使用してください:)

obj = {
   1 : { name : 'bob' , dinner : 'pizza' },
   2 : { name : 'john' , dinner : 'sushi' },
   3 : { name : 'larry', dinner : 'hummus' }
}

_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]
1
TomDotTom

特定のパスに一致する最初のリーフアイテムのネストされたサイトマップ構造を検索する必要がありました。 .map().filter().reduceを使用して、次のコードを思いつきました。パス/cに一致する最後に見つかったアイテムを返します。

var sitemap = {
  nodes: [
    {
      items: [{ path: "/a" }, { path: "/b" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    },
    {
      items: [{ path: "/c" }, { path: "/d" }]
    }
  ]
};

const item = sitemap.nodes
  .map(n => n.items.filter(i => i.path === "/c"))
  .reduce((last, now) => last.concat(now))
  .reduce((last, now) => now);

Edit 4n4904z07

0
Marc