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

在JavaScript对象数组中按id查找对象,javascript,arrays,javascript-objects,Javascript,Arrays,Javascript Objects,我有一个数组: myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.] var result = $.grep(myArray, function(e){ return e.id == id; }); 我无法更改数组的结构。我被传递了一个45的id,我想得到数组中该对象的“bar” 如何在JavaScript或使用jQuery中实现这一点?尝试以下方法 function findById(source, id) {

我有一个数组:

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]
var result = $.grep(myArray, function(e){ return e.id == id; });
我无法更改数组的结构。我被传递了一个45的id,我想得到数组中该对象的“bar”

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

尝试以下方法

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

我认为最简单的方法是以下方法,但它在InternetExplorer8或更早版本上不起作用:

var result = myArray.filter(function(v) {
    return v.id === '45'; // Filter out the appropriate one
})[0].foo; // Get result and access the foo property

迭代数组中的任何项。对于您访问的每个项目,请检查该项目的id。如果匹配,请将其返回

如果您只是想了解codez:

function getId(array, id) {
    for (var i = 0, len = array.length; i < len; i++) {
        if (array[i].id === id) {
            return array[i];
        }
    }
    return null; // Nothing found
}

您可以使用以下功能轻松实现这一点:

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

工作示例:

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

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

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

myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}, etc.]
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
}

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

您可以从中试用Sugarjs

它在数组上有一个非常好的方法,.find。因此,您可以找到如下元素:

array.find( {id: 75} );
您还可以将具有更多属性的对象传递给它,以添加另一个where子句

注意到Sujjs扩展了原生对象,有些人认为这很邪恶…

有一个很好的方法:

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

它应该按id返回对象。

您可以使用过滤器

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

get_my_obj = getById(73, myArray);
ECMAScript 2015 JavaScript ES6提供了 数组上的方法:

var myArray=[ {id:1,name:bob}, {id:2,name:dan}, {id:3,name:barb}, ] //获取与id 2匹配的数组项 var item=myArray.finditem=>item.id==2; //印刷品
console.logitem.name 只要浏览器支持,第5版2009年12月,这应该可以工作,几乎一行:

var bFound = myArray.some(function (obj) {
    return obj.id === 45;
});
从开始,这是一个实际返回所需元素的函数,如果未找到,则返回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-loop:


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

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

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一样,如果发现一个对象,函数将返回该对象,而不是数组。

基于已接受的答案:

jQuery:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)
或咖啡脚本:

foo = $.grep myArray, (e) -> e.id == foo_id
myArray.pop foo

即使在纯JavaScript中,也可以通过使用内置的数组过滤函数来实现这一点:

Array.prototype.filterObjects = function(key, value) {
    return this.filter(function(x) { return x[key] === value; })
}
现在只需传递id代替key,传递45代替value,就可以得到与id为45匹配的完整对象。那就是

myArr.filterObjects("id", "45");

我真的很喜欢Aaron Digulla提供的答案,但我需要保留我的对象数组,以便以后可以遍历它。所以我把它改成

变量索引器={}; 对于var i=0;i<数组长度;i++{ 索引器[array[i].id]=parsenti; } //然后可以使用访问数组中的对象属性
array[indexer[id]].property以下是我如何在纯JavaScript中使用它,以我能想到的最简单的方式在ECMAScript 3或更高版本中使用。一旦找到匹配项,它就会返回

var getKeyValueById = function(array, key, id) {
    var testArray = array.slice(), test;
    while(test = testArray.pop()) {
        if (test.id === id) {
            return test[key];
        }
    }
    // return undefined if no matching id is found in array
    return;
}

var myArray = [{'id':'73', 'foo':'bar'}, {'id':'45', 'foo':'bar'}]
var result = getKeyValueById(myArray, 'foo', '45');

// result is 'bar', obtained from object with id of '45'
使用本机 如果找到,则返回对象元素,否则返回false使用find方法:

发件人:

如果数组中的元素满足提供的测试函数,find方法将返回数组中的第一个值。否则将返回undefined

如果要查找其索引,请使用findIndex:

发件人:

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

如果要获取匹配元素的数组,请改用以下方法:

myArray.filter(x => x.id === '45');
这将返回一个对象数组。如果要获取foo属性数组,可以使用以下方法:


旁注:find或filter等方法不受IE等旧浏览器的支持,因此,如果您想支持这些浏览器,您应该使用来传输代码。

虽然这里有许多正确的答案,但其中许多都没有解决这样一个事实,即如果执行多次,这是一个不必要的昂贵操作。在极端情况下,这可能是实际性能问题的原因

在现实世界中,如果您正在处理大量项目,并且性能是一个问题,那么最初构建查找的速度要快得多:

var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});
然后,您可以在固定时间内获取以下项目:

var bar = o[id];

你也可以考虑使用一个映射而不是一个对象作为查找。 :

使用Array.prototype.filter函数

演示:

JSON

滤器


如果您多次这样做,您可以设置地图ES6:

const map = new Map( myArray.map(el => [el.id, el]) );
然后你可以简单地做:

map.get(27).foo
我们可以使用Jquery方法$.each/$.grep

使用ES6语法:

Array.find, Array.filter, Array.forEach, Array.map
或者使用Lodash,下划线更一般和简短

function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}

在您的例子中,Ex.var element=findFromArraymyArray,'id',45将给出整个元素。

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

经过一些搜索,我发现使用简单的代码很容易处理:

代码:


正如其他人所指出的,在数组中查找一个对象时,这是一种方法。但是,如果使用此方法找不到您的对象,您的程序将崩溃: 常量myArray=[{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}]; const res=myArray.findx=>x.id=='100'.foo;//哦! /* 错误: 未捕获的TypeError:无法读取未定义的属性“foo” */演出 今天2020.06.20,我在MacOs High Sierra上对所选解决方案在Chrome 81.0、Firefox 77.0和Safari 13.1上进行测试

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

令人惊讶的是,基于MapK的Chrome和Safari解决方案比基于对象{}L的解决方案快得多 令人惊讶的是,在Safari for small Array上,基于对象{}L的解决方案比传统的用于E的解决方案要慢 令人惊讶的是,在Firefox上,基于MapK的小型阵列解决方案比传统的E 结论当搜索对象总是存在时 使用传统E的解决方案对于小型阵列最快,对于大型阵列最快 对于大型阵列,使用cache J的解决方案速度最快,而对于小型阵列,使用cache J的解决方案速度则为中速 基于find A和findIndex B的解决方案对于小型阵列是快速的,而对于大型阵列则是中速的 基于$.map H的解决方案在小型阵列上速度最慢 基于reduced的解决方案在大型阵列上速度最慢 结论:当搜索对象不存在时 基于传统for E的解决方案在小型和大型阵列上都是最快的,但Chrome小型阵列则是第二快的 基于reduced的解决方案在大型阵列上速度最慢 使用缓存J的解决方案是中速的,但如果我们在缓存中保存具有空值的密钥(此处未执行此操作),则可以加快速度,因为我们希望避免缓存中的无限内存消耗,以防搜索到许多不存在的密钥 细节 寻求解决方案

没有预先计算: J解决方案使用“内部”缓存,其速度取决于搜索元素重复的频率 预先计算 我做了四次测试。在测试中,我希望在10次循环迭代中找到5个对象,对象ID在迭代过程中不会改变-因此我调用测试方法50次,但只有前5次具有唯一的ID值:

小数组10个元素和搜索的对象始终存在-您可以执行它 大数组10k元素和搜索对象始终存在-您可以执行它 小数组10个元素和搜索的对象永远不存在-您可以执行它 大数组10k元素和搜索对象从不存在-您可以执行它 测试代码如下所示

函数Aarr,id{ 返回arr.findo=>o.id==id; } 函数Barr,id{ 设idx=arr.findIndexo=>o.id==id; 返回arr[idx]; } 函数Carr,id{ 返回arr.filtero=>o.id==id[0]; } 函数Darr,id{ 返回arr.reducea,b=>a.id==id&&a | | b.id==id&&b; } 功能耳环{ 对于变量i=0;i{ 如果obj.id==id{ retObj=obj; 返回false; } }; 返回retObj; } 函数Garr,id{ return$.greparr,e=>e.id==id[0]; } 函数Harr,id{ 返回$.mapmyArray,functionval{ 返回val.id==id?val:null; }[0]; } 函数Iarr,id{ 返回u.findarr,o=>o.id==id; } 让J==>{ 让cache=newmap; 返回函数Jarr,id,el=null{ 返回cache.getid | | el=arr.findo=>o.id==id,cache.setid,el,el; } }; 函数Karr,id{ 返回mapK.getid } 函数Larr,id{ 返回mapL[id]; } // ------- //试验 // ------- console.log'Find id=5'; myArray=[…Array10].mapx,i=>{id':`${i}`,'foo':`bar_${i}`; const mapK=new Map myArray.mapel=>[el.id,el]; 常量mapL={};myArray.forEachel=>mapL[el.id]=el; [A,B,C,D,E,F,G,H,I,J,K,L].forEachf=>console.log`${F.name}:${JSON.stringifyfmyArray,'5'}; log'Whole array',JSON.stringifymyArray;
这段代码只展示了经过测试的代码。我很好奇,与通常的相比,这里有什么性能优势吗?@Igor Zinov'yev:是的,这些ES5阵列工具肯定会对性能产生影响。每个元素都会执行一个单独的函数,因此它不是reall

和直接for循环相比,y快。那么你是说它会慢一些?而且,据我所知,它将始终扫描整个阵列,而for循环将在第一次匹配时终止。如果您需要IE8的支持,只需输入以下内容:如果没有ID为的元素,则此代码将抛出一个错误这不值得自己回答,但在现代浏览器中,这个解决方案可以写成:如果你想提高效率,请注意,这个例子可能比使用过滤器更快。请参阅Rick的例子,因为这个例子在找到第一个匹配项后返回,而过滤器即使在找到匹配项后也会继续在整个数组中运行。这一个也不需要为每个项创建额外的数组或调用函数。@Rick,关于这个答案最有趣的一点显然是您可以将firebug控制台添加到JSFIDLE的输出窗口中。这比记录并告诉其他人打开控制台查看输出要好得多。令人惊叹的由于到目前为止还没有人提到过它,我想补充一点,AngularJS也有一个方法。@JaredPar使用===而不是==,会更安全,以避免JavaScript的==运算符出现奇怪的问题。@VickyChijwani:将字符串与字符串进行比较时有什么问题吗?嗯,如果您绝对确定e.id和id都是字符串,我想可以使用==。但如果您不确定,您可能会面临问题,因为==0为真,而===0为假。更不用说===似乎更快。基本上我总是使用===因为它的工作原理与其他编程语言中的==完全相同。在JavaScript中,我认为“===”不存在。这里的许多答案在查找唯一值时提供了预期的行为;基本上,您可以通过以下事实来识别它们:它们提前返回或中断循环,或者指示较低级别的构造停止迭代。参见JaredPar的答案中的一个典型示例,以及Aaronius对该答案的评论中的相同见解。一般来说,人们用这种方式区分过滤函数和查找函数,但术语各不相同。虽然效率更高,但这仍然是一个线性搜索,因此如果您想使用哈希表,请参阅Aaron Digulla的答案小心impl。细节,正是我想要的。有趣的是,当我只需要修改从CouchDB接收到的数据并将其转换为适合我需要的格式时,我试图通过每次循环来将其复杂化,从列表中删除我发现的每个项目+1先生!这很聪明。我无法想象其他人是如何被每一次使用的数组所说服的;在循环中,如果你知道只有一个对象可以找到,那么这是一个很好的选择/改进?@irJvV:不,那根本没有意义。如果需要执行许多查找,则上面的代码非常有用。如果只查看一次,则创建查找对象是浪费时间。对于记录,通常比下划线更有效的Lo-Dash也有类似的方法。Docs here:如果您只需要一个对象,那么使用findWhere将更有效,因为在找到一个结果后,搜索将不会再进一步。@永远从u3;的文档开始。find:函数在找到可接受的元素后立即返回,并且不会遍历整个列表。可能是因为它看起来仍然非常实验性,并且没有很多浏览器支持它,这可以简化为myArray.findd=>d.id==45.foo@Shaggy甚至myArray.find{id}=>id==45.foo。但这是一个在ES2015语法和现在一样受支持之前编写的老答案@Gothdo是线程中当前最新的。@Shaggy如果.find返回未定义,则您的优化将抛出一个错误。因此,此解决方案只能在保证匹配的情况下使用。@HerbertPeters如果您想确保始终可以进行空检查,这将非常容易:myArray.findd=>d.id==45?.foo。您可以使用return obj.id==5来缩短代码?obj:假;我经常使用$.each来迭代数组。@marcel:那不行。由于返回false将结束循环,因此它将仅在对象是数组中的第一项时找到该对象。几乎。bFound只是一个布尔值,当元素满足所需条件时它才是真的。好吧,它是邪恶的,因为新的EcmaScript版本可能会引入同名的新方法。猜猜看,这是什么。我的建议是,如果您想扩展本机原型,请始终使用更具体的名称,将最简单的名称留给未来的标准开发。这条评论已经有近2年的历史了,今天我宁愿使用lodash。但是,如果您愿意,您可以在sugarjs网站上阅读有关此主题的内容。他们很好地支持您的观点:op确实特别要求使用javascript或jquery解决方案。我忘记了jquery的映射自动删除空元素的事实。这听起来对我和地图的共同概念有误导性,因为
e结果与原始集合的长度不同。对于旧浏览器,请使用Ployfill:@Danilo如何在嵌套对象中搜索@TobiasBeuving-使用Array.find的也是纯JS,应该在第一次查找时停止,这样效率会更高。不要修改你不拥有的对象。不要修改你不拥有的对象。@Gothdo我同意。如果有人不知道函数将返回对象,而不是数组,则可能会出错,但我认为这取决于用户。请注意,IE8及以下版本不支持array.reduce。使用与faster相同的解决方案查找数组中的项。但是parseInt在这里是多余的。对于多个测试条件,它会是这样的:myArray.findx=>x.id=='45'&&x.color=='red'。对于我来说,这是目前为止最好的答案。不需要jQuery也不需要创建新的辅助数组。myArray.findx=>x.id===“45”它在mac PCmyArray.findx=>x.id==“45”上不起作用。foo;如果没有id为“45”的对象,则引发异常。是否可以在find方法中添加多个条件?如何在嵌套对象中搜索?Like pets=false应在嵌套循环中的obj.info上返回两个objects.use.filter方法。var getPerson=functionname{return jsonObj.filterfunctionobj{return obj.info.filterfunctioninfo{return pets===false;};};};};}您也可以使用es6样式。。。const filterData=jsonObj.filterobj=>obj.name==='Alex'未完成的工作
myArray.filter(x => x.id === '45').map(x => x.foo);
var items = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];

var lookup = items.reduce((o,i)=>o[i.id]=o,{});
var bar = o[id];
var jsonObj =[
 {
  "name": "Me",
  "info": {
   "age": "15",
   "favColor": "Green",
   "pets": true
  }
 },
 {
  "name": "Alex",
  "info": {
   "age": "16",
   "favColor": "orange",
   "pets": false
  }
 },
{
  "name": "Kyle",
  "info": {
   "age": "15",
   "favColor": "Blue",
   "pets": false
  }
 }
];
var getPerson = function(name){
    return jsonObj.filter(function(obj) {
      return obj.name === name;
    });
}
const map = new Map( myArray.map(el => [el.id, el]) );
map.get(27).foo
var data= [];
$.each(array,function(i){if(n !== 5 && i > 4){data.push(item)}}
var data = $.grep(array, function( n, i ) {
  return ( n !== 5 && i > 4 );
});
Array.find, Array.filter, Array.forEach, Array.map
function findFromArray(array,key,value) {
        return array.filter(function (element) {
            return element[key] == value;
        }).shift();
}
var items = mydata.filter(function(item){
    return item.word.toLowerCase().startsWith( 'gk );
})