如何确定对象是否在数组中

Cas*_*jne 168 javascript

我需要确定一个对象是否已经存在于javascript中的数组中.

例如(虚拟代码):

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);
Run Code Online (Sandbox Code Playgroud)

现在"carBrands"数组包含所有实例.我现在正在寻找一个快速的解决方案来检查car1,car2,car3或car4的实例是否已经在carBrands数组中.

例如:

var contains =  carBrands.Contains(car1); //<--- returns bool.
Run Code Online (Sandbox Code Playgroud)

car1和car4包含相同的数据但是不同的实例它们应该被测试为不相等.

我是否在创建时向对象添加了哈希值?或者有更快的方法在Javascript中执行此操作.

我在这里寻找最快的解决方案,如果是脏的,那么它必须是;)在我的应用程序中,它必须处理大约10000个实例.

没有jquery

cdh*_*wie 157

使用这样的东西:

function containsObject(obj, list) {
    var i;
    for (i = 0; i < list.length; i++) {
        if (list[i] === obj) {
            return true;
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,containsObject(car4, carBrands)是真的.删除carBrands.push(car4);呼叫,它将返回false.如果稍后扩展为使用对象来存储这些其他汽车对象而不是使用数组,则可以使用以下内容:

function containsObject(obj, list) {
    var x;
    for (x in list) {
        if (list.hasOwnProperty(x) && list[x] === obj) {
            return true;
        }
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

这种方法也适用于数组,但是当在数组上使用时,它将比第一个选项慢一点.

  • 它应该是 JSON.stringify(list[i]) === JSON.stringify(obj) 而不是 list[i] === obj (4认同)
  • @MartínNieva可能是因为您要查找的对象不在列表中,而是一个比较深度相等的不同对象。在这种情况下,使用 lodash 的 [`isEqual()`](https://lodash.com/docs/4.17.15#isEqual) 比滥用序列化更好。(事实上​​,使用 lodash,整个解决方案就变成了一个单行方案,结合了 `_.some` 和 `_.isEqual`:`_.some(list, v =&gt; _.isEqual(v, o))`。 ) (3认同)
  • 不敢相信 Python 中如此简单的事情在 js 中竟然如此复杂。 (3认同)

Fra*_*rax 110

你为什么不使用javascript数组的indexOf方法?

看看这个:MDN indexOf Arrays

简单地说:

carBrands.indexOf(car1);
Run Code Online (Sandbox Code Playgroud)

它将返回car1的索引(数组中的位置).如果在阵列中找不到car1,它将返回-1.

http://jsfiddle.net/Fraximus/r154cd9o

编辑:请注意,在问题中,要求是检查数组中引用同一对象,而不是新对象.即使新对象的内容与数组中的对象相同,它仍然是一个不同的对象.正如评论中所提到的,对象在JS中通过引用传递,并且同一对象可以在多个结构中多次存在.
如果你想创建一个新对象并检查数组是否包含与你的对象相同的对象,这个答案将不起作用(Julien的小提琴下面),如果你想检查数组中是否存在同一个对象,那么这个答案将工作.查看这里和评论中的小提琴.

  • 当你试图在数组中找到对象时,indexOf总是返回-1 ...这里的小例子:http://jsfiddle.net/7B7dQ/1/ (104认同)
  • 如果它显然不起作用,为什么这有40个upvotes? (62认同)
  • 请记住,JS中的对象是通过引用传递的.这意味着_two具有相同属性和相同值的两个对象不是同一个object_.这也意味着_an对象实际上可以同时存在于多个数组中.示例:http://jsfiddle.net/7B7dQ/33/ (35认同)
  • 男士们,在问题上,OP想要的东西就像`carBrands.Contains(car1)`.如果你做carBrands.indexOf(car1),IT工作.看看这个:http://jsfiddle.net/Fraximus/r154cd9o/ (12认同)
  • 在Julien的小提琴中,它不起作用,因为它是一个新的对象,即使它们是相同的. (10认同)
  • 我不明白为什么这么多人说这个答案需要删除。这是一个很好、简洁的答案,回答了 OP 的问题,而 Julien 的例子并没有反映出 OP 试图做什么。@Frax 提出了很好的观点。我怀疑很多人都懒得去真正看这个问题 (2认同)

ste*_*tef 18

你可以使用jQuery的grep方法:

$.grep(carBrands, function(obj) { return obj.name == "ford"; });
Run Code Online (Sandbox Code Playgroud)

但是,当你指定没有jQuery时,你可以只做一个函数的派生.从源代码:

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"; });
Run Code Online (Sandbox Code Playgroud)


Fak*_* 10 15

最近被FP错误所困扰,阅读了许多关于功能范例如何与Javascript完美契合的精彩报道

为了完整起见,我复制了代码并提出了两种可以在功能上完成的方法.

    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
Run Code Online (Sandbox Code Playgroud)

如果您需要支持旧版浏览器使用polyfill,IE9 +和Edge似乎不支持它.位于MSDN页面的polyfill部分

另外,我想提出一个更新的cdhowie答案

// 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)
}
Run Code Online (Sandbox Code Playgroud)

  • 相同的方法,但实际上比较对象:`arr.some((e) =&gt; Object.entries(e).toString() === Object.entries(obj).toString())` (3认同)
  • 当我将 `var car6 = {name:'ford'};` 添加到您的第一个解决方案并尝试 `carBrands.includes(car6)` 时,它返回 false。你能解释一下吗? (2认同)

Uti*_*You 11

尝试Array.prototype.some()

MDN Array.prototype.some


    function isBiggerThan10(element, index, array) {
      return element > 10;
    }
    [2, 5, 8, 1, 4].some(isBiggerThan10);  // false
    [12, 5, 8, 1, 4].some(isBiggerThan10); // true

Run Code Online (Sandbox Code Playgroud)


zzz*_*Bov 9

你可以使用相等运算符:==.默认情况下,通过引用检查对象,因此您甚至不需要使用===运算符.

试试这个,只要确保你使用正确的变量引用代替car1:

var i, car, l = cars.length;

for (i = 0; i < l; i++)
{
  if ((car = cars[i]) == car1)
  {
    break;
  }
  else car = null;
}
Run Code Online (Sandbox Code Playgroud)

编辑添加:

提到了一个数组扩展,所以这里是它的代码:

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;
};
Run Code Online (Sandbox Code Playgroud)

请注意,我正在缓存长度值,因为Array的length属性实际上是一个访问器,它比内部变量略慢.


Jin*_*esh 7

我用underscorejavascript库来调整这个问题.

function containsObject(obj, list) {
 var res = _.find(list, function(val){ return _.isEqual(obj, val)});
 return (_.isObject(res))? true:false;
}
Run Code Online (Sandbox Code Playgroud)

有关上面示例中使用的下划线函数,请参阅underscore.js文档.

注意:我的解决方案不是纯javascript,因为它使用其他js库.我添加此信息只是为了提供信息.


小智 7

我会在数组上使用属性/值的泛型迭代器.不需要jQuery.

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;  
}
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试一下,您可以使用 JavaScript some() 方法来查明 JavaScript 数组是否包含对象。

<script>
// An array of objects
var persons = [{name: "Harry"}, {name: "Alice"}, {name: "Peter"}];

// Find if the array contains an object by comparing the property value
if(persons.some(person => person.name === "Peter")){
    alert("Object found inside the array.");
} else{
    alert("Object not found.");
}
</script>
Run Code Online (Sandbox Code Playgroud)