我有一个数组:

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

我无法更改阵列的结构。我收到了一个45的id,我想得到数组中该对象的“bar”。

如何在JavaScript或使用jQuery实现这一点?


当前回答

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

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

其他回答

只要浏览器支持ECMA-262,第5版(2009年12月),这应该可以工作,几乎只有一行:

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

从aggaton的答案开始,这是一个实际返回所需元素(如果找不到则返回null)的函数,给定数组和一个回调函数,该函数返回“正确”元素的truthy值:

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

请记住,这在IE8-上本就不起作用,因为它不支持某些功能。可以提供polyfill,或者总是有经典的for循环:

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

它实际上更快、更紧凑。但如果你不想重新发明轮子,我建议使用下划线或lodash之类的实用程序库。

下面的代码将帮助您从数据中的嵌套对象中搜索值。

const updatedData = myArrayOfObjects.filter((obj: any) => Object.values(obj).some((val: any) => {
   if (typeof (val) == typeof ("str")) {
      return val.toString().includes(Search)
   } else {
      return Object.values(val).some((newval: any) => {
         if (newval !== null) {
            return newval.toString().includes(Search)
         }
      })
   }
}))

表演

今天2020.06.20我在Chrome 81.0、Firefox 77.0和Safari 13.1上对MacOs High Sierra进行了测试,以获得所选的解决方案。

使用预先计算的解决方案的结论

具有预计算(K,L)的解决方案比其他解决方案(快得多),不会与它们进行比较-可能它们使用了一些特殊的内置浏览器优化

令人惊讶的是,基于Map(K)的Chrome和Safari解决方案比基于对象{}(L)的解决方案快得多令人惊讶的是,Safari上基于对象{}的小型阵列解决方案(L)比传统的(E)慢令人惊讶的是,Firefox上基于Map(K)的小阵列解决方案比传统的(E)慢

搜索对象始终存在时的结论

使用传统for(E)的解决方案对于小阵列最快,对于大阵列最快对于大型阵列,使用缓存(J)的解决方案是最快的,而对于小型阵列,则是中等速度基于find(A)和findIndex(B)的解决方案对于小阵列很快,对于大阵列则很快基于$.map(H)的解决方案在小型阵列上是最慢的基于reduce(D)的解决方案在大型阵列上最慢

搜索对象从不存在时的结论

基于传统for(E)的解决方案在小型和大型阵列上都是最快的(除了Chrome小型阵列,后者速度第二快)基于reduce(D)的解决方案在大型阵列上最慢使用缓存(J)的解决方案是中等速度的,但如果我们将具有空值的键也保存在缓存中,则可以加快速度(这里没有这样做,因为我们希望避免在搜索许多不存在的键时在缓存中无限制地消耗内存)

细节

对于解决方案

无需预先计算:ABCDEFGH我J(J解决方案使用“内部”缓存,其速度取决于搜索元素重复的频率)带有预先计算KL

我进行了四次测试。在测试中,我希望在10次循环迭代中找到5个对象(对象ID在迭代过程中不会改变)-所以我调用测试方法50次,但只有前5次具有唯一的ID值:

小数组(10个元素)和搜索对象始终存在-您可以在此处执行大数组(10k个元素)和搜索对象始终存在-您可以在此处执行小数组(10个元素)和搜索对象从不存在-您可以在此处执行大数组(10k个元素)和搜索对象从不存在-您可以在这里执行

测试代码如下

函数A(arr,id){返回arr.find(o=>o.id==id);}函数B(arr,id){设idx=arr.findIndex(o=>o.id==id);返回arr[idx];}函数C(arr,id){返回arr.filter(o=>o.id==id)[0];}函数D(arr,id){return arr.reduce((a,b)=>(a.id==id&&a)||(b.id==id&&b));}函数E(arr,id){对于(var i=0;i<arr.length;i++)如果(arr[i].id==id)返回arr[i];返回null;}函数F(arr,id){var retObj={};$.each(arr,(索引,obj)=>{如果(obj.id==id){retObj=对象;return false;}});返回retObj;}函数G(arr,id){return$.grep(arr,e=>e.id==id)[0];}函数H(arr,id){return$.map(myArray,函数(val){返回val.id==id?val:空;})[0];}函数I(arr,id){return _.find(arr,o=>o.id==id);}设J=(()=>{let cache=new Map();返回函数J(arr,id,el=null){返回cache.get(id)||(el=arr.find(o=>o.id==id),cache.set(id,el),el);}})();函数K(arr,id){return mapK.get(id)}函数L(arr,id){返回mapL[id];}// -------------//测试// -------------console.log('查找id=5');myArray=[…Array(10)].map((x,i)=>({'id':`${i}`,'foo':`bar_${i}`));const mapK=新地图(myArray.Map(el=>[el.id,el]));常量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('hole 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>此代码段仅显示经过测试的代码

搜索对象始终存在的小数组的Chrome测试结果示例

查找数组索引的方法:

index = myArray.map((i) => i.id).indexOf(value_of_id);
item = myArray[index];