如何在JavaScript中的对象数组中查找值?


90

我有一个对象数组:

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

我希望能够在对象/数组中搜索键为“晚餐”的位置,并查看其是否与“寿司”匹配。

我知道jQuery具有$ .inArray,但它似乎不适用于对象数组。也许我错了。indexOf似乎也只能在一个数组级别上工作。

没有功能或现有代码吗?


这已经被问过了。您必须编写自己的函数或使用其他库。
菲利克斯·克林

1
请注意,Object在Javascript中保留的Object是对象对象,即所有对象的母亲。
亚当斯2011年

1
问题和已接受的答案与多维数组无关,而更多的是通过其项的属性值对一维数组进行过滤。=>他们没有解决我的问题“在多维数组中查找值”。
Martin Schneider

Answers:


211

如果您有一个数组,例如

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

您可以使用filterArray对象的方法:

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

在较新的JavaScript实现中,可以使用函数表达式:

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

您可以搜索"dinner": "sushi"使用过map

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" }]

我确定您可以将其概括为任意键和值!


7
请记住,这些解决方案是ECMAScript 5的一部分,而IE8不支持。kangax.github.com/es5-compat-table 尽管我更喜欢@adamse的答案,但alex的“老旧的糟糕浏览器”更友好。虽然不确定性能。
EasyCo 2012年

@SalmanA-问题或解决方案都不是指jQuery。使用的是JavaScript filter(),而不是jQuery专用的$ .filter()- tutorialspoint.com/javascript/array_filter.htm
Tapirboy 2013年

如EasyCo所述,IE8不支持过滤器功能。但是,它很容易添加到Array原型中,因此可以在脚本开头带有小功能的任何浏览器中使用。过滤器文档中对此进行了概述。它提供了ECMA-262中指定的确切功能,因此实际上是一样的。
达林

1
我刚刚添加了一个使用jQuery grep方法的答案。与您正在做的事情相同的概念可能会合乎您的意思,但是与jQuery有关并且对浏览器友好。
Zach Lysobey 2013年

我的返回变量是否不断收到参考错误,是否有原因?我尝试了返回“ x”的前两个答案,并且一直说它是不确定的……
Evan Lalo

18

jQuery有一个内置方法jQuery.grep,其filter功能类似于@adamse的Answers中的 ES5 函数,并且在较旧的浏览器上应该可以正常工作。

使用亚当斯的例子:

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" }]

10
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不是有效的密钥。


几乎赞成这一观点,但帖子中没有任何解释。
mickmackusa

10

如果您将经常进行此搜索,请考虑更改对象的格式,因此晚餐实际上是关键。这有点像在数据库表中分配主群集键。因此,例如:

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

您现在可以像这样轻松地访问它: Object['sushi']['name']

或者,如果对象确实如此简单(只是对象中的“名称”),则可以将其更改为:

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

然后像这样访问它Object['sushi']

显然,这样重组数据对象并非总是可行或对您有利,但重点是,有时最好的答案是考虑是否以最佳方式构造了数据对象。像这样创建密钥可以更快并创建更简洁的代码。


1
爱你的答案,但是我发现语法有问题:我的工作方式只有这样:obj = {“ pizza”:{“ name”:“ bob”},“ sushi”:{“ name”:“ john”}} alert( obj ['pizza'] ['name']); 但还是。谢谢!发现我在寻找什么!)
aleXela

@alexela谢谢alexela!我用您的敏锐观察力更新了答案!我只是在OP的帖子中复制了该示例,而忽略了添加引号,但是您是对的-除非至少在值周围有引号(假设它们是值而不是变量),否则它将不起作用。
dallin

3

您可以使用Alasql库在数组中找到对象:

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
我不确定这真的应该被否决。当需求变得比单个过滤器或reduce调用更为复杂时,类似SQL的查询就更易于推理和编写。Alasql是一个非常令人印象深刻的库,但是对于上面的示例,坦率地说有点过大。
TomDotTom

1
如果对象本身源自SQL源,则此答案是纯天才。
edwardsmarkf

1

您可以使用简单的for in循环:

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

这里已经有很多很好的答案,所以为什么不再使用lodash或underscore这样的库呢:)

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

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

0

我必须在嵌套的站点地图结构中搜索适合给定路径的第一个叶项。我仅使用.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);

编辑4n4904z07


0

我会尽量不要重新发明轮子。我们将对象扫描用于所有数据处理需求。从概念上讲,它很简单,但可以带来很多很棒的东西。这是您将如何解决您的特定问题的方法

资料定义

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

逻辑

const objectScan = require('object-scan');

const scanner = (input) => {
  let obj = null;
  objectScan(['*.dinner'], {
    filterFn: (key, value, { parents }) => {
      if (value === 'sushi') {
        obj = parents[0];
      }
    },
    breakFn: () => obj !== null
  })(data);
  return obj;
};

const result = scanner(data);

输出量

// => result
{
  "name": "john",
  "dinner": "sushi"
}

0

如果要通过搜索功能查找特定对象,请尝试以下操作:

    function findArray(value){

        let countLayer = dataLayer.length;
        for(var x = 0 ; x < countLayer ; x++){

            if(dataLayer[x].user){
                let newArr = dataLayer[x].user;
                let data = newArr[value];
                return data;
            }

        }

        return null;

    }

    findArray("id");

这是一个示例对象:

layerObj = {
    0: { gtm.start :1232542, event: "gtm.js"},
    1: { event: "gtm.dom", gtm.uniqueEventId: 52},
    2: { visitor id: "abcdef2345"},
    3: { user: { id: "29857239", verified: "Null", user_profile: "Personal", billing_subscription: "True", partners_user: "adobe"}
}

代码将迭代并找到“用户”数组,并将搜索您要在其中寻找的对象。

我的问题是,当每次窗口刷新时数组索引都发生变化时,它位于第3个或第二个数组中,但这并不重要。

对我来说就像一个魅力!

在您的示例中,它要短一些:

function findArray(value){

    let countLayer = Object.length;
    for(var x = 0 ; x < countLayer ; x++){

        if(Object[x].dinner === value){
            return Object[x];
        }

    }

    return null;

}

findArray('sushi');
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.