我有一个数组:

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

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

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


当前回答

最近,我不得不面对同样的事情,我需要从一个巨大的数组中搜索字符串。

经过一番搜索,我发现用简单的代码就能轻松处理:

代码:

var items = mydata.filter(function(item){
    return item.word.toLowerCase().startsWith( 'gk );
})

看见https://jsfiddle.net/maheshwaghmare/cfx3p40v/4/

其他回答

从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之类的实用程序库。

使用jQuery的过滤方法:

 $(myArray).filter(function()
 {
     return this.id == desiredId;
 }).first();

这将返回具有指定Id的第一个元素。

它还具有良好的C#LINQ格式的优点。

表演

今天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测试结果示例

此解决方案也可能有帮助:

Array.prototype.grep = function (key, value) {
    var that = this, ret = [];
    this.forEach(function (elem, index) {
        if (elem[key] === value) {
            ret.push(that[index]);
        }
    });
    return ret.length < 2 ? ret[0] : ret;
};
var bar = myArray.grep("id","45");

我将其设置为$.grep,如果找到一个对象,函数将返回该对象,而不是数组。

ECMAScript 2015(JavaScript ES6)提供find()数组上的方法:

var myArray=[{id:1,name:“bob”},{id:2,名称:“dan”},{id:3,名称:“barb”},]//抓取与id“2”匹配的Array项var item=myArray.find(item=>item.id===2);//打印console.log(item.name);

它在没有外部库的情况下工作。但是,如果您想要更旧的浏览器支持,您可能需要包含此polyfill。