题 在JavaScript对象数组中按id查找对象


我有一个数组:

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

我无法改变数组的结构。我被传递了 45,我想得到 'bar' 对于数组中的该对象。

我如何在JavaScript或使用jQuery中执行此操作?


1109
2017-09-09 15:42


起源




答案:


使用 find() 方法:

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

MDN

find() 如果数组中的元素满足提供的测试函数,则method返回数组中的值。除此以外 undefined 被退回。


如果你想找到它 指数 相反,使用 findIndex()

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

MDN

findIndex() method返回数组中第一个满足提供的测试函数的元素的索引。否则返回-1。


如果要获取匹配元素的数组,请使用 filter() 方法改为:

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

这将返回一个对象数组。如果你想得到一个数组 foo 属性,你可以这样做 map() 方法:

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

旁注:方法如 find() 要么 filter(),和 箭头功能 旧版浏览器(如IE)不支持,因此如果您想支持这些浏览器,则应使用以下代码来转换代码 巴别塔 (随着 填充工具)。


433
2018-02-14 21:11



因此,对于多个测试条件,它将类似于:myArray.find(x => x.id ==='45'&& x.color =='red')。foo - Apqu
对我来说,到目前为止最好的答案。不需要jQuery也不需要创建新的辅助数组。 - Arthur Cantarela
myArray.find(x => x.id === '45')它在mac PC上不起作用 - Govinda Rajbhar
@ T.J.Crowder我认为将MDN中的polyfill复制粘贴到代码中并不是一个好主意。相反,你应该使用带有polyfill的npm包。而Babel确实包括用于ES2015 +功能的polyfill 巴别塔,填充工具 包。 - Michał Perłakowski
@MichałPerłakowski - 我确实说过 “(巴别塔还可以包括某些东西的填充物)” 并且同意,自从MDN复制粘贴以来,polyfilling已经发展。 :-) - T.J. Crowder


由于您已经在使用jQuery,因此可以使用 grep的 用于搜索数组的函数:

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

结果是一个包含找到的项目的数组。如果您知道对象始终存在并且只出现一次,则可以使用 result[0].foo 获得价值。否则,您应该检查结果数组的长度。例:

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

1421
2017-09-09 15:54



它使用起来更安全 === 代替 ==,以避免JavaScript的奇怪问题 == 运营商。 - Vicky Chijwani
@VickyChijwani:将字符串与字符串进行比较时是否有任何问题? - Guffa
好吧,如果你是 绝对 确定两者 e.id 和 id 将是字符串,我想它可以使用 ==。但如果你不确定,你可能会面临问题(因为 '' == 0 是 true 但 '' === 0 是 false)。更何况 === 似乎更快(stackoverflow.com/questions/359494/...)。 - Vicky Chijwani
基本上我总是用 === 因为它有效 究竟 喜欢 == 在其他编程语言中。我认为 == 在JavaScript中不存在。 - Vicky Chijwani
@de。这里的许多答案提供了查找唯一值时的预期行为;你可以基本上通过它们早期返回或从循环中断(或指示较低级别的构造停止迭代)来识别它们。请参阅JaredPar对一个规范示例的回答,以及Aaronius对该答案的评论。通常,人们以这种方式区分“过滤”和“查找”功能,但术语各不相同。虽然效率更高,但这仍然是线性搜索,因此如果您想使用哈希表,请参阅Aaron Digulla的答案(谨防impl。详细信息)。 - tne


另一种解决方案是创建查找对象:

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和对象将被共享。


344
2017-09-09 15:50



正是我在寻找什么。有趣的是我试图通过每次尝试循环来过度复杂化,从我发现它时从列表中删除每个项目,当我只需要改变从CouchDB接收的数据并将其转换为对我有用的格式需要。 +1先生! - slickplaid
这很聪明。我无法想象其他人如何通过查看每个用途的阵列来说服他人。 - Aladdin Mhemed
只要您不依赖于属性的顺序: stackoverflow.com/questions/4886314/... - Marle1
正在休息;如果你知道只有一个对象可以找到,那么在循环中一个很好的选择/改进? - irJvV
@irJvV:不,这根本没有意义。如果您需要进行许多查找,上面的代码很有用。如果你只看一次,那么创建一个 lookup 对象是浪费时间。 - Aaron Digulla


ECMAScript 2015 提供 找() 数组上的方法:

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

它没有外部库。但如果你想要 较旧的浏览器支持 你可能想要包括 这种polyfill


147
2018-02-10 22:32



可能导致它仍然看起来很实验,并没有很多浏览器支持它, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - lejonl
这可以简化为 myArray.find(d=>d.id===45).foo;。 - Shaggy
@Shaggy甚至 myArray.find(({ id }) => id === 45).foo。但这是在ES2015语法得到支持之前编写的旧答案。 @ Gothdo的 回答 目前是该帖子中最新的。 - Rúnar Berg
@Shaggy如果.find()返回undefined,那么优化会抛出错误。因此,此解决方案仅适用于保证匹配的情况。 - Herbert Peters
@HerbertPeters如果你想确定你总是可以进行无效检查,这将非常容易 可选链接: myArray.find(d => d.id === 45)?.foo。 - Rúnar Berg


Underscore.js 有一个很好的方法:

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

138
2017-11-22 12:52



对于记录,Lo-Dash(通常比Underscore更高性能)具有类似的方法。文件在这里: lodash.com/docs#find - user456584
如果您只期望一个对象,那么使用findWhere会更有效,因为在找到一个结果后,搜索将不再进一步。 - Foreever
@Foreever来自_.find的文档:“函数一找到可接受的元素就返回,并且不会遍历整个列表。” - GijsjanB


我认为最简单的方法如下,但它不适用于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

123
2017-09-09 15:46



我很好奇,与平时相比,这里有什么性能优势 for? - Igor Zinov'yev
@Igor Zinov'yev:是的,这些ES5阵列工具肯定会对性能产生影响。为每个元素执行单独的函数,因此与直接元素相比,它不会非常快 for 循环。 - pimvdb
所以你说它会慢一点?此外,就我所见,它总是扫描整个阵列,而对 for 循环将在第一场比赛中终止。 - Igor Zinov'yev
@Igor Zinov'yev:是的,这是一个天真的解决方案,我承认。 - pimvdb
如果您需要IE8的支持,请将其放入: stackoverflow.com/questions/7153470/... - Adam Grant


请尝试以下方法

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

64
2017-09-09 15:45



这不值得回答,但在现代浏览器中,这个解决方案可以写成: jsfiddle.net/rwaldron/j3vST - Rick
如果你想提高效率,请注意这个例子可能比使用filter()更快(参见Rick的例子),因为一旦找到第一个匹配的项目就会返回,而filter()在找到一个完整的数组后继续运行比赛。这个也没有为每个项目创建额外数组或调用函数的成本。 - Aaronius
@Rick,关于这个答案最有趣的事情显然是你可以将firebug控制台添加到jsFiddle的输出窗口中。这比记录并告诉其他人打开控制台以查看输出要好得多。真棒! - KyleMit
由于目前还没有人提到它,我想补充说AngularJS也有 过滤 方法。 - Eno
@JaredPar stackoverflow.com/questions/44550439/... - Valay


myArray.filter(function(a){ return a.id == some_id_you_want })[0]

42
2018-04-16 17:31



适用于IE9 + kangax.github.io/compat-table/es5/#Array.prototype.filter - Justin
适用于旧版浏览器的Ployfill: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Justin
@Danilo如何在嵌套对象中搜索? stackoverflow.com/questions/44550439/... - Valay


上面的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');

30
2017-07-13 20:34





你可以使用过滤器,

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

get_my_obj = getById(73, myArray);

13
2017-09-13 09:43



@TobiasBeuving - 使用Array.find()的那个也是普通的JS,应该在第一个查找时停止,这样会更有效率。 - Adrian Lynch


你可以轻松地使用 地图() 功能:

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/


13
2017-09-09 15:46



我忘记了jQuery的事实 map 自动删除 null 元素。这听起来很误导我和共同的概念 map,因为结果与原始集合的长度不同。 - MaxArt