通过ID在JavaScript对象数组中查找对象

2020/09/16 09:31 · javascript ·  · 0评论

我有一个数组:

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)的支持,所以如果你想支持这些浏览器,你应该使用transpile代码巴贝尔(用填充工具)。

由于您已经在使用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
}

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

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在数组上提供了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

Underscore.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');

您可以使用map()函数轻松获得此信息

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/

您可以使用过滤器

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

get_my_obj = getById(73, myArray);

尽管这里有许多正确的答案,但其中许多答案并没有解决这样的事实,即如果进行多次以上,这将是不必要的昂贵操作。在极端情况下,这可能是造成实际性能问题的原因。

在现实世界中,如果您要处理很多项目,而性能是一个问题,那么最初构建查找的速度会更快:

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

var lookup = items.reduce((o,i)=>o[i.id]=o,{});

然后,您可以像这样在固定时间获取物品:

var bar = o[id];

您可能还考虑使用Map而不是对象作为查询:https : //developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map

使用本机 Array.reduce

var array = [ {'id':'73' ,'foo':'bar'} , {'id':'45' ,'foo':'bar'} , ];
var id = 73;
var found = array.reduce(function(a, b){
    return (a.id==id && a) || (b.id == id && b)
});

如果找到,则返回对象元素,否则返回 false

如果您多次执行此操作,则可以设置地图(ES6):

const map = new Map( myArray.map(el => [el.id, el]) );

然后,您可以简单地执行以下操作:

map.get(27).foo

这是我将以纯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'

更通用,更简短

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

在您的情况下 var element = findFromArray(myArray,'id',45)这将为您提供整个元素。

性能

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

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

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

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

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

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

在此处输入图片说明

不存在搜索对象的结论

  • 基于传统for(E)的解决方案在大型和大型阵列上速度最快(Chrome-small阵列除外,后者排名第二)
  • reduce大数组中基于(D)的解决方案最慢
  • 使用高速缓存(J)的解决方案速度中等,但是如果我们在高速缓存中还保存具有空值的键,则可以加快速度(此处未执行此操作是因为我们希望避免在高速缓存中使用许多不存在的键时不受限制的内存消耗)被搜索)

在此处输入图片说明

细节

解决方案

  • 无需预先计算:A
    B
    C
    D
    E
    F
    G
    H
    I
    J(J解决方案使用“内部”缓存,其速度取决于搜索元素重复的频率)
  • 预先计算
    K
    L

我执行了四个测试。在测试中,我想在10次循环迭代中找到5个对象(对象ID在迭代过程中不变)-因此我将测试方法调用50次,但只有前5次具有唯一的ID值:

  • 小数组(10个元素)和搜索到的对象始终存在-您可以在此处执行
  • 大数组(1万个元素)和搜索到的对象始终存在-您可以在此处执行
  • 小数组(10个元素)和搜索对象从不存在-您可以在此处执行
  • 大数组(10k个元素)和搜索到的对象永远不存在-您可以在此处执行

经测试的代码如下所示

Chrome的示例结果测试了始终存在搜索对象的小型阵列的结果

在此处输入图片说明

您可以从http://sugarjs.com/试用Sugarjs

它对Arrays有很好的方法.find因此,您可以找到这样的元素:

array.find( {id: 75} );

您也可以将具有更多属性的对象传递给它,以添加另一个“ where-clause”。

请注意,Sugarjs扩展了本机对象,有些人认为这很邪恶。

以公认的答案为基础:

jQuery的:

var foo = $.grep(myArray, function(e){ return e.id === foo_id})
myArray.pop(foo)

或CoffeeScript:

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

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

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

码:

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

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

从20k字符串中搜索

遍历数组中的任何项目。对于您访问的每个商品,请检查该商品的ID。如果匹配,则将其返回。

如果您只想编码:

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
}

同样,使用ECMAScript 5的Array方法:

function getId(array, id) {
    var obj = array.filter(function (val) {
        return val.id === id;
    });

    // Filter returns an array, and we just want the matching item.
    return obj[0];
}

只要浏览器支持ECMA-262,第5版(2009年12月),它就可以工作,几乎只有一种形式:

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

您甚至可以通过使用内置的数组“过滤器”函数在纯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");

使用Array.prototype.filter()功能。

演示https : //jsfiddle.net/sumitridhal/r0cz0w5o/4/

JSON格式

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

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

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

使用ES6语法:

Array.find, Array.filter, Array.forEach, Array.map

或使用Lodash https://lodash.com/docs/4.17.10#filter,下划线https://underscorejs.org/#filter

我真的很喜欢亚伦·迪古拉(Aaron Digulla)提供的答案,但需要保留我的对象数组,以便稍后进行迭代。所以我修改为

	var indexer = {};
	for (var i = 0; i < array.length; i++) {
	    indexer[array[i].id] = parseInt(i);
	}
	
	//Then you can access object properties in your array using 
	array[indexer[id]].property

正如其他人指出的那样,这.find()是在数组中查找一个对象时要走的路。但是,如果使用此方法找不到对象,则程序将崩溃:

const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
const res = myArray.find(x => x.id === '100').foo; // Uh oh!
/*
Error:
"Uncaught TypeError: Cannot read property 'foo' of undefined"
*/

可以通过.find()在使用前检查结果是否已定义来.foo解决此问题。Modern JS允许我们通过可选的链接轻松地做到这一点undefined如果找不到对象,则返回它,而不是使您的代码崩溃:

const myArray = [{'id':'73','foo':'bar'},{'id':'45','foo':'bar'}];
const res = myArray.find(x => x.id === '100')?.foo; // No error!
console.log(res); // undefined when the object cannot be found

用:

var retObj ={};
$.each(ArrayOfObjects, function (index, obj) {

        if (obj.id === '5') { // id.toString() if it is int

            retObj = obj;
            return false;
        }
    });
return retObj;

它应该通过id返回一个对象。

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

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

aggaton的答案开始,这是一个实际上返回null给定元素(如果没有找到的话)arraycallback函数,并且给出了返回“正确”元素的真实值函数:

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

只需记住,这在IE8-上本身不起作用,因为它不支持some可以提供一个polyfill,或者总是有经典的for循环:

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

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

本文地址:http://javascript.askforanswer.com/tongguoidzaijavascriptduixiangshuzuzhongchazhaoduixiang.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!