Подтвердить что ты не робот

Эффективное определение индекса объекта внутри массива

Я пытаюсь найти индекс объекта в массиве. Я знаю, что есть способ сделать это с помощью underscore.js, но я пытаюсь найти эффективный способ без underscore.js. Вот что я имею:

var arrayOfObjs = [{
  "ob1": "test1"
}, {
  "ob2": "test1"
}, {
  "ob1": "test3"
}];

function FindIndex(key) {
  var rx = /\{.*?\}/;            // regex: finds string that starts with { and ends with }
  var arr = [];                  // creates new array
  var str = JSON.stringify(arrayOfObjs);          // turns array of objects into a string
  for (i = 0; i < arrayOfObjs.length; i++) {      // loops through array of objects
    arr.push(str.match(rx)[0]);                   // pushes matched string into new array
    str = str.replace(rx, '');                    // removes matched string from str
  }
  var Index = arr.indexOf(JSON.stringify(key));   // stringfy key and finds index of key in the new array
  alert(Index);
}

FindIndex({"ob2": "test1"});

JSFIDDLE

Это работает, но я боюсь, что это не очень эффективно. Любые альтернативы?

4b9b3361

Ответ 1

Здесь один из способов сделать это, несколько надежно и немного более эффективно, используя some() и останавливаясь, как только объекты не совпадают и т.д.

var arrayOfObjs = [{
  "ob1": "test1"
}, {
  "ob2": "test1"
}, {
  "ob1": "test3"
}];

function FindIndex(key) {
    var index = -1;

    arrayOfObjs.some(function(item, i) {
    	var result = Object.keys(key).some(function(oKey) {
            return (oKey in item && item[oKey] === key[oKey]);
        });
        if (result) index = i;
        return result;
    });
    
    return index;
}

var index = FindIndex({"ob2": "test1"});

document.body.innerHTML = "'{\"ob2\": \"test1\"}' is at index : " + index;

Ответ 2

Хэш-таблица с примером доступа.

var arrayOfObjs = [{ "obj1": "test1" }, { "obj2": "test1" }, { "obj1": "test3" }],
    hash = {};

arrayOfObjs.forEach(function (a, i) {
    Object.keys(a).forEach(function (k) {
        hash[k] = hash[k] || {};
        hash[k][a[k]] = i;
    });
});

document.write('<pre>' + JSON.stringify(hash['obj2']['test1'], 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(hash, 0, 4) + '</pre>');

Ответ 3

Один из способов сделать это - использовать every, чтобы увидеть, имеет ли каждый ключ в "фильтре" соответствующее, правильное значение в объекте. every гарантирует, что цикл прекратится, как только он обнаружит несоответствующее или отсутствующее значение.

function log(msg) {
  document.querySelector('pre').innerHTML += msg + '\n';
}

var arr = [
  {
    a: 1
  },
  {
    b: 2
  },
  {
    c: 3,
    d: 4
  },
  {
    a: 1 // Will never reach this since it finds the first occurrence
  }
];

function getIndex(filter) {
  var keys = Object.keys(filter);
  for (var i = 0, len = arr.length; i < len; i++) {
    var obj = arr[i];
    var match = keys.every(function(key) {
      return filter[key] === obj[key];
    });
    if (match) {
      return i;
    }
  }
  
  return -1;
}

log(getIndex({ a: 1 }));
log(getIndex({ b: 2 }));
log(getIndex({ c: 3 }));
log(getIndex({ c: 3, d: 4 }));
log(getIndex({ e: 5 })); // Doesn't exist, won't find it
<pre></pre>

Ответ 4

Для альтернативы вашему специально построенному подходу метод lodash findIndex делает именно это для вас:

var arrayOfObjs = [{
  "ob1": "test1"
}, {
  "ob2": "test1"
}, {
  "ob1": "test3"
}];

_.findIndex(arrayOfObjs, {"ob2": "test1"}); // => 1

Ответ 5

Так как тестирование равенства на двух разных объектах всегда будет возвращать false, вы можете сначала проверить ключи, а затем значения,

используя сокращение:

var arrayOfObjs = [{
  "ob1": "test1"
}, {
  "ob2": "test1" , k2:2
}, {
  "ob1": "test3"
}];

function getI( obj, arr){
 const checkK= Object.keys(obj);
 return arr.reduce((ac,x,i) => {
  if ( checkK.every(z =>  x[z] && obj[z] === x[z]) )
    ac.push(i);
  return ac;
  },[])
}

document.write( 'result is :'+ getI({ob2:'test1', k2:2},arrayOfObjs))

Ответ 6

findIndex не будет работать в старых браузерах, но был разработан для этой конкретной цели.

var arrayOfObjs = [{
  "ob1": "test1"
}, {
  "ob2": "test1"
}, {
  "ob1": "test3"
}];

function FindIndex(key) {
  return arrayOfObjs.findIndex(
    obj => Object.keys(key).every(name => key[name] === obj[name])
  );
}

alert(FindIndex({"ob2": "test1"})); // 1