我有一个数组:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]
我无法更改数组的结构。我正在传递一个id参数 45
,我想获取该数组中该对象的'bar'
值。
如何在JavaScript或使用jQuery实现?
我有一个数组:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]
我无法更改数组的结构。我正在传递一个id参数 45
,我想获取该数组中该对象的'bar'
值。
如何在JavaScript或使用jQuery实现?
使用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()
这样的方法,以及 箭头函数 不受旧版浏览器(如 IE)的支持,因此,如果您想要支持这些浏览器,应该使用 Babel (带 polyfill)对代码进行转译。
既然您已经在使用jQuery,那么可以使用 grep 函数来搜索数组:
var result = $.grep(myArray, function(e){ return e.id == id; });
结果是一个包含找到的项目的数组。如果你知道对象始终存在且仅出现一次,那么你可以使用 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
}
==
操作符的奇怪问题,最好使用 ===
,两者的差别在于前者比较严格。 - Vicky Chijwanie.id
和id
都是字符串,那么使用==
可能是可以的。但如果你不确定,你可能会遇到问题(因为'' == 0
是true
但'' === 0
是false
)。更不用说===
似乎更快(http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use#comment14900957_359494)。 - Vicky Chijwani===
,因为它与其他编程语言中的 ==
完全 相同。在 JavaScript 中,我认为 ==
是不存在的。 - Vicky Chijwani另一个解决方案是创建一个查找对象:
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和对象将被共享,因此这不需要更多的内存。
ECMAScript 2015(JavaScript ES6)在数组上提供了 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);
它可以在不使用外部库的情况下工作。但是,如果你想要支持旧浏览器,你可能需要包含此 Polyfill。
myArray.find(d=>d.id===45).foo;
。 - ShaggymyArray.find(({ id }) => id === 45).foo
。但这是一个旧的答案,写于ES2015语法得到充分支持之前。@Gothdo的答案目前是该线程中最新的。 - Rúnar BergUnderscore.js有一个很好的方法可以实现这个:
myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'},etc.]
obj = _.find(myArray, function(obj) { return obj.id == '45' })
我认为最简单的方法如下,但它不适用于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
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;
}
myArray.filter(function(a){ return a.id == some_id_you_want })[0]
一个通用且更加灵活的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');
今天2020.06.20,我在Chrome 81.0、Firefox 77.0和Safari 13.1上对选择的解决方案进行了MacOs High Sierra测试。
使用预计算的解决方案(K,L)比其他解决方案(快得多得多)快,并且不会与它们进行比较 - 可能它们使用了一些特殊的内置浏览器优化。
Map
(K) 的解决方案比基于对象{}
(L) 的解决方案更快。{}
(L) 的解决方案比传统的for
(E) 更慢。Map
(K) 的解决方案比传统的for
(E) 更慢。for
(E) 的解决方案是最快的,对于大数组也很快。find
(A) 和findIndex
(B) 的解决方案在小数组上很快,在大数组上速度中等。$.map
(H) 的解决方案在小数组上最慢。reduce
(D) 的解决方案在大数组上最慢。for
(E)的解决方案在小型和大型数组上最快(除了Chrome小数组,其中它是第二快的)reduce
(D)的解决方案在大型数组上最慢针对以下解决方案:
我进行了四项测试。在这些测试中,我想在10个循环迭代中找到5个对象(对象ID在迭代过程中不变)- 因此我调用被测试的方法50次,但只有前5次具有唯一的ID值:
测试代码如下所示
function A(arr, id) {
return arr.find(o=> o.id==id);
}
function B(arr, id) {
let idx= arr.findIndex(o=> o.id==id);
return arr[idx];
}
function C(arr, id) {
return arr.filter(o=> o.id==id)[0];
}
function D(arr, id) {
return arr.reduce((a, b) => (a.id==id && a) || (b.id == id && b));
}
function E(arr, id) {
for (var i = 0; i < arr.length; i++) if (arr[i].id==id) return arr[i];
return null;
}
function F(arr, id) {
var retObj ={};
$.each(arr, (index, obj) => {
if (obj.id == id) {
retObj = obj;
return false;
}
});
return retObj;
}
function G(arr, id) {
return $.grep(arr, e=> e.id == id )[0];
}
function H(arr, id) {
return $.map(myArray, function(val) {
return val.id == id ? val : null;
})[0];
}
function I(arr, id) {
return _.find(arr, o => o.id==id);
}
let J = (()=>{
let cache = new Map();
return function J(arr,id,el=null) {
return cache.get(id) || (el=arr.find(o=> o.id==id), cache.set(id,el), el);
}
})();
function K(arr, id) {
return mapK.get(id)
}
function L(arr, id) {
return mapL[id];
}
// -------------
// TEST
// -------------
console.log('Find id=5');
myArray = [...Array(10)].map((x,i)=> ({'id':`${i}`, 'foo':`bar_${i}`}));
const mapK = new Map( myArray.map(el => [el.id, el]) );
const mapL = {}; myArray.forEach(el => mapL[el.id]=el);
[A,B,C,D,E,F,G,H,I,J,K,L].forEach(f=> console.log(`${f.name}: ${JSON.stringify(f(myArray, '5'))}`));
console.log('Whole array',JSON.stringify(myArray));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
This snippet only presents tested codes
在 Chrome 中对小型数组进行搜索,且待搜索的对象总是存在的示例测试结果
find
方法中添加多个条件吗? - Si8