JS использует indexOf для массива объектов

Я хочу использовать indexOf() для массива объектов. Например:

var arr;
var arr[0] = {a: 1, b: 2};
var arr[1] = {a: 1, b: 3};
var obj = {a: 1, b: 2};

console.log(arr.indexOf(obj));

Это выведет -1, потому что arr[0] не равен obj. Как я могу заставить эту работу (то есть вывести 0)?

3 ответа

Вы должны были бы сравнить свойства. Примерно так будет работать:

var arr = [];
arr[0] = {a: 1, b: 2};
arr[1] = {a: 1, b: 3};

console.log(arr.findIndex(o => o.a === 1 && o.b === 2));
//0
console.log(arr.findIndex(o => o.a === 1 && o.b === 3));
//1

Я создал similar функция, которая сравнивает почти все, что-то назад:

function similar(needle, haystack, exact){
  if(needle === haystack){
    return true;
  }
  if(needle instanceof Date && haystack instanceof Date){
    return needle.getTime() === haystack.getTime();
  }
  if(!needle || !haystack || (typeof needle !== 'object' && typeof haystack !== 'object')){
    return needle === haystack;
  }
  if(needle === null || needle === undefined || haystack === null || haystack === undefined || needle.prototype !== haystack.prototype){
    return false;
  }
  var keys = Object.keys(needle);
  if(exact && keys.length !== Object.keys(haystack).length){
    return false;
  }
  return keys.every(function(k){
    return similar(needle[k], haystack[k]);
  });
}
var obj1 = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
var obj2 = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
console.log(similar(obj1, obj2, true)); // true for exact match
obj2.newProp = 'new value'; // extra haystack prop added
console.log(similar(obj1, obj2, true)); // true for exact - result is false here
console.log(similar(obj1, obj2)); // not exact - obj1 properties and values are in obj2

Конечно similar можно сделать, чтобы найти similarIndex из needle (что угодно) в haystack (массив чего угодно), вот так:

function similar(needle, haystack, exact){
  if(needle === haystack){
    return true;
  }
  if(needle instanceof Date && haystack instanceof Date){
    return needle.getTime() === haystack.getTime();
  }
  if(!needle || !haystack || (typeof needle !== 'object' && typeof haystack !== 'object')){
    return needle === haystack;
  }
  if(needle === null || needle === undefined || haystack === null || haystack === undefined || needle.prototype !== haystack.prototype){
    return false;
  }
  var keys = Object.keys(needle);
  if(exact && keys.length !== Object.keys(haystack).length){
    return false;
  }
  return keys.every(function(k){
    return similar(needle[k], haystack[k]);
  });
}
function similarIndex(needle, haystack, exact){
  for(var i=0,l=haystack.length; i<l; i++){
    if(similar(needle, haystack[i], exact)){
      return i;
    }
  }
  return -1;
}
var objArray = [{a:1, b:[5, 'wtf'], c:{another:'cool', neat:'not', num:1}, d:'simple string'}, {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'}, {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:4}, d:'simple string'}];
var testObj = {a:1, b:[5, 'word'], c:{another:'cool', neat:'not', num:1}, d:'simple string'};
console.log(similarIndex(testObj, objArray, true)); // exact - index is 1 in this case
objArray[1].newProp = 'new value'; // haystack array element 1 gets new property and value
console.log(similarIndex(testObj, objArray, true)); // exact - -1 result here
console.log(similarIndex(testObj, objArray)); // not exact - index 1

array.findIndex() функция вернет индекс для первого значения, что результаты функции сравнения true, У меня есть функция, которую я использую для сравнения, если два объекта равны, которые можно использовать в этом примере.

var obj = {a: 1, b: 2};
var arr = [];
arr[0] = {a: 1, b: 2};
arr[1] = {a: 1, b: 3};

var idx = arr.findIndex(element => areObjsEqual(element,obj));
console.log(`The index is: ${idx}`);

//Function to check if two js objects are equal
function areObjsEqual(a, b) {
    // Create arrays of property names
    var aProps = Object.getOwnPropertyNames(a);
    var bProps = Object.getOwnPropertyNames(b);

    // If number of properties is different,
    // objects are not equivalent
    if (aProps.length != bProps.length) { return false;}
    
    //loop through the object and compare the property values
    for (var i = 0; i < aProps.length; i++) {
        var propName = aProps[i];
        // If values of same property are not equal,
        // objects are not equivalent
        if (a[propName] !== b[propName]) {
            return false;
        }
    }
    // If we made it this far, objects
    // are considered equivalent
    return true;
}

Другие вопросы по тегам