How to determine if object is in array
我需要确定一个对象是否已经存在于javascript中的数组中。
EG(DimyMac):
1 2 3 4 5 6 7 8 9 10 11 | var carBrands = []; var car1 = {name:'ford'}; var car2 = {name:'lexus'}; var car3 = {name:'maserati'}; var car4 = {name:'ford'}; carBrands.push(car1); carBrands.push(car2); carBrands.push(car3); carBrands.push(car4); |
现在"carbrands"数组包含所有实例。我现在正在寻找一个快速的解决方案来检查car1、car2、car3或car4的实例是否已经在carbrands数组中。
如:
1 | var contains = carBrands.Contains(car1); //<--- returns bool. |
car1和car4包含相同的数据,但它们是不同的实例,因此应将它们测试为不相等。
在创建时是否向对象添加类似哈希的内容?或者有更快的方法在javascript中实现这一点。
我在这里寻找最快的解决方案,如果是脏的,那么它必须是;)在我的应用程序中,它必须处理大约10000个实例。
没有jQuery
使用类似的方法:
1 2 3 4 5 6 7 8 9 10 | function containsObject(obj, list) { var i; for (i = 0; i < list.length; i++) { if (list[i] === obj) { return true; } } return false; } |
在这种情况下,
1 2 3 4 5 6 7 8 9 10 | function containsObject(obj, list) { var x; for (x in list) { if (list.hasOwnProperty(x) && list[x] === obj) { return true; } } return false; } |
这种方法也适用于数组,但在数组上使用时,比第一个选项慢一点。
为什么不使用javascript数组的indexof方法?
签出:数组的MDN索引
简单地做:
1 | carBrands.indexOf(car1); |
它将返回car1的索引(数组中的位置)。如果在数组中找不到car1,它将返回-1。
http://jsfiddle.net/fraximus/r154cd9o
编辑:请注意,在问题中,要求检查数组中引用的同一对象,而不是新对象。即使新对象的内容与数组中的对象相同,它仍然是不同的对象。如注释所述,对象在JS中通过引用传递,同一对象在多个结构中可以存在多次。如果要创建一个新对象并检查数组中是否包含与新对象相同的对象,则此答案将不起作用(下面是Julien的小提琴),如果要检查数组中是否存在相同的对象,则此答案将起作用。看看这里和评论中的小提琴。
您可以使用jquery的grep方法:
1 | $.grep(carBrands, function(obj) { return obj.name =="ford"; }); |
但是,当您没有指定jquery时,您可以对函数进行派生。从源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function grepArray( elems, callback, inv ) { var ret = []; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { if ( !inv !== !callback( elems[ i ], i ) ) { ret.push( elems[ i ] ); } } return ret; } grepArray(carBrands, function(obj) { return obj.name =="ford"; }); |
最近被FP bug咬了很多,阅读了许多功能性范式与JavaScript相吻合的精彩报道。
为了完整性的缘故,我复制了代码,并提出了两种可以在功能上完成的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var carBrands = []; var car1 = {name:'ford'}; var car2 = {name:'lexus'}; var car3 = {name:'maserati'}; var car4 = {name:'ford'}; var car5 = {name:'toyota'}; carBrands.push(car1); carBrands.push(car2); carBrands.push(car3); carBrands.push(car4); // ES6 approach which uses the includes method (Chrome47+, Firefox43+) carBrands.includes(car1) // -> true carBrands.includes(car5) // -> false |
如果需要支持较旧的浏览器,请使用polyfill,似乎ie9+和edge不支持它。位于msdn页面的polyfill部分
或者,我想提出一个对CDhowie的更新答案
1 2 3 4 5 6 7 8 9 10 11 12 13 | // ES2015 syntax function containsObject(obj, list) { return list.some(function(elem) { return elem === obj }) } // or ES6+ syntax with cool fat arrows function containsObject(obj, list) { return list.some(elem => elem === obj) } |
尝试array.prototype.some()。
mdn array.prototype.some
1 2 3 4 5 | function isBiggerThan10(element, index, array) { return element > 10; } [2, 5, 8, 1, 4].some(isBiggerThan10); // false [12, 5, 8, 1, 4].some(isBiggerThan10); // true |
您只需使用相等运算符:
尝试这个方法,只要确保使用正确的变量引用来代替
1 2 3 4 5 6 7 8 9 10 | var i, car, l = cars.length; for (i = 0; i < l; i++) { if ((car = cars[i]) == car1) { break; } else car = null; } |
编辑添加:
提到了一个数组扩展,下面是它的代码:
1 2 3 4 5 6 7 8 9 | Array.prototype.contains = Array.prototype.contains || function(obj) { var i, l = this.length; for (i = 0; i < l; i++) { if (this[i] == obj) return true; } return false; }; |
注意,我正在缓存长度值,因为数组的
我将在数组上使用属性/值的一般迭代器。不需要jquery。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | arr = [{prop1: 'val1', prop2: 'val2'}, {prop1: 'val3', prop2: 'val4'}]; objectPropInArray(arr, 'prop1', 'val3'); // <-- returns true function objectPropInArray(list, prop, val) { if (list.length > 0 ) { for (i in list) { if (list[i][prop] === val) { return true; } } } return false; } |
我使用
1 2 3 4 | function containsObject(obj, list) { var res = _.find(list, function(val){ return _.isEqual(obj, val)}); return (_.isObject(res))? true:false; } |
有关上述示例中使用的下划线函数,请参阅underline.js文档。
注意:我的解决方案不是纯JavaScript,因为它使用的是其他JS库。我添加这个只是为了提供信息。
您可以尝试基于属性对数组进行排序,例如:
1 2 3 | carBrands = carBrands.sort(function(x,y){ return (x == y) ? 0 : (x > y) ? 1 : -1; }); |
然后可以使用迭代例程检查
1 2 3 4 | carBrands[Math.floor(carBrands.length/2)] // change carBrands.length to a var that keeps // getting divided by 2 until result is the target // or no valid target exists |
大于或小于目标值,依此类推,这将使您快速浏览数组以查找对象是否存在。
这个函数是为了检查一个唯一的字段。ARG 1:具有选定数据的数组ARG 2:检查的关键ARG 3:必须"验证"的价值
1 2 3 4 5 6 7 8 9 10 11 12 13 | function objectUnique( array, field, value ) { var unique = true; array.forEach(function ( entry ) { if ( entry[field] == value ) { unique = false; } }); return unique; } |
我知道这是一篇老文章,但我想提供一个jquery插件版本和我的代码。
1 2 3 4 | // Find the first occurrence of object in list, Similar to $.grep, but stops searching function findFirst(a,b){ var i; for (i = 0; i < a.length; ++i) { if (b(a[i], i)) return a[i]; } return undefined; } |
用途:
1 | var product = $.findFirst(arrProducts, function(p) { return p.id == 10 }); |