В массиве объектов самый быстрый способ найти индекс объекта, атрибуты которого соответствуют поиску

Я занимался серфингом вокруг немного, пытаясь найти эффективный способ сделать это, но нигде не стал. У меня есть массив объектов, который выглядит так:

array[i].id = some number;
array[i].name = some name;

Что я хочу сделать, так это найти ИНДЕКСЫ объектов, где id равен, например, один из 0,1,2,3 или 4. Полагаю, я мог бы сделать что-то вроде:

var indexes = [];
for(i=0; i<array.length; i++) {
  (array[i].id === 0) ? { indexes[0] = i }
  (array[i].id === 1) ? { indexes[1] = i }
  (array[i].id === 2) ? { indexes[2] = i }
  (array[i].id === 3) ? { indexes[3] = i }
  (array[i].id === 4) ? { indexes[4] = i }
}

Пока это будет работать, оно выглядит довольно дорогостоящим и медленным (не говоря уже о уродливом), особенно если array.length может быть большим. Любые идеи о том, как это сделать? Я думал об использовании array.indexOf, но я не вижу, как заставить синтаксис. Это

array.indexOf(this.id === 0);

например, возвращает undefined, как и должно быть. Спасибо заранее!

Ответ 1

Возможно, вы хотели бы использовать функции более высокого порядка, такие как "карта". Предполагая, что вы хотите искать по атрибуту 'field':

var elementPos = array.map(function(x) {return x.id; }).indexOf(idYourAreLookingFor);
var objectFound = array[elementPos];

Ответ 2

Самый простой и простой способ найти индекс элемента в массиве.

Синтаксис ES5: [{id:1},{id:2},{id:3},{id:4}].findIndex(function(obj){return obj.id == 3})

Синтаксис ES6: [{id:1},{id:2},{id:3},{id:4}].findIndex(obj => obj.id == 3)

Ответ 3

Новый метод Array . filter() будет хорошо работать для этого:

var filteredArray = array.filter(function (element) { 
    return element.id === 0;
});

jQuery также может сделать это с помощью . grep()

edit: стоит упомянуть, что обе эти функции просто перебираются под капот, между ними не будет заметной разницы в производительности и откатом вашей собственной функции фильтра, но зачем заново изобретать колесо.

Ответ 4

array.forEach(function (elem, i) {  // iterate over all elements of array
    indexes[elem.id] = i;           // take the found id as index for the
});                                 // indexes array and assign i

результат - это список поиска для id. с данным id мы получаем индекс записи.

Ответ 5

var indices = [];
var IDs = [0, 1, 2, 3, 4];

for(var i = 0, len = array.length; i < len; i++) {
    for(var j = 0; j < IDs.length; j++) {
        if(array[i].id == ID) indices.push(i);
    }
}

Ответ 6

Поскольку нет ответа с использованием регулярного массива find:

var one = {id: 1, name: 'one'};
var two = {id: 2, name:'two'}
var arr = [one, two] 

var found = arr.find((a) => a.id === 2)

found === two // true

arr.indexOf(found) // 1

Ответ 7

Новый способ использования ES6

let picked_element = array.filter(element => element.id === 0);

Ответ 8

Мне кажется, что вы можете создать простой итератор с обратным вызовом для тестирования. Например:

function findElements(array, predicate)
{
    var matchingIndices = [];

    for(var j = 0; j < array.length; j++)
    {
        if(predicate(array[j]))
           matchingIndices.push(j);
    }

    return matchingIndices;
}

Затем вы можете вызвать так:

var someArray = [
     { id: 1, text: "Hello" },
     { id: 2, text: "World" },
     { id: 3, text: "Sup" },
     { id: 4, text: "Dawg" }
  ];

var matchingIndices = findElements(someArray, function(item)
   {
        return item.id % 2 == 0;
   });

// Should have an array of [1, 3] as the indexes that matched

Ответ 9

Адаптация ответа Tejs для mongoDB и Robomongo я изменилась

matchingIndices.push(j);

к

matchingIndices.push(NumberInt(j+1));

Ответ 10

Использование функции ES6 map:

let idToFind = 3;
let index = someArray.map(obj => obj.id).indexOf(idToFind);

Ответ 11

Подводя итог всему замечательному ответу выше и дополнению моего ответа, касающегося поиска всех индексов из некоторого комментария.

  • Чтобы вернуть индекс первого вхождения.

const array = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 2 }];
const idYourAreLookingFor = 2;

//ES5 
//Output: 1
array.map(function (x) { return x.id; }).indexOf(idYourAreLookingFor);

//ES6 
//Output: 1
array.findIndex(obj => obj.id === idYourAreLookingFor);

Ответ 12

Если вы заботитесь о производительности, не используйте поиск, фильтр, карту или любой из описанных выше методов.

Вот пример, демонстрирующий самый быстрый метод. ЗДЕСЬ ссылка на актуальный тест

Блок настройки

var items = []

for(var i = 0; i < 1000; i++) {
    items.push({id: i + 1})
}

var find = 523

Самый быстрый метод

var index = -1
for(var i = 0; i < items.length; i++) {
    if(items[i].id === find) {
        index = i;
        break;
    }
}

Более медленные методы

items.findIndex(item => item.id === find)

МЕДЛЕННЫЙ метод

items.map(item => item.id).indexOf(find);

Ответ 13

const index = array.findIndex(item => item.id === 'your-id');

Это должно сделать вам индекс элемента в массиве с id === your-id

array = [ {id:1}, {id:2} ];

const index = array.findIndex(item => item.id === 2);

console.log(index);

Ответ 14

Как я еще не могу прокомментировать, я хочу показать решение, которое я использовал на основе метода Umair Ahmed, но если вы хотите найти ключ вместо значения:

[{"a":true}, {"f":true}, {"g":false}]
.findIndex(function(element){return Object.keys(element)[0] == "g"});

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

Ответ 15

Я создал небольшую утилиту под названием super-array, где вы можете получить доступ к элементам в массиве с помощью уникального идентификатора с помощью O (1 ) сложность. Пример:

const SuperArray = require('super-array');

const myArray = new SuperArray([
  {id: 'ab1', name: 'John'},
  {id: 'ab2', name: 'Peter'},
]);

console.log(myArray.get('ab1')); // {id: 'ab1', name: 'John'}
console.log(myArray.get('ab2')); // {id: 'ab2', name: 'Peter'}

Ответ 16

var test = [
  {id:1, test: 1},
  {id:2, test: 2},
  {id:2, test: 2}
];

var result = test.findIndex(findIndex, '2');

console.log(result);

function findIndex(object) {
  return object.id == this;
}

вернет индекс 1 (работает только в ES 2016)

Ответ 17

Мне нравится этот метод, потому что его легко сравнить с любым значением объекта, независимо от того, насколько глубоко оно вложено.

 while(i<slides.length && slides[i].props.data!==value){
  console.log("data ->", slides[i].props.data, "value",value);
  i++; 
}
// i now hows the index value for the match.