2017-01-17 3 views
0

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

Например:

var cars = [ 
    { id:23, make:'honda', color: 'green' }, 
    { id:36, make:'acura', color:'silver' }, 
    { id:18, make:'ford', color:'blue' }, 
    { id:62, make:'ford', color:'green' }, 
]; 

Пусть мне нужно один из этих записей, и я знаю эту запись уникальной; например, где id = 18.

Прямо сейчас, Я делаю это следующим образом:

function select(key,val,arr){ 

    for(var i in arr){ 
     if(arr[i][key]==val) return(arr[i]); 
    } 
    return(null); // object not present in arr 
} 


var id = 18; 
var car = select('id', id, cars); 

// car = { id:18, make:'ford', color:'blue' } 

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

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

+1

не использовать 'for ... in' на' array' –

ответ

1

Вы можете использовать Array.prototype.map(), чтобы создать теневой массив, который поможет вам быстрее искать, или, кроме того, вы можете создать объект index, как показано ниже, он будет напрямую возвращать нужный вам индекс.

var cars = [ 
    { id:23, make:'honda', color: 'green' }, 
    { id:36, make:'acura', color:'silver' }, 
    { id:18, make:'ford', color:'blue' }, 
    { id:62, make:'ford', color:'green' }, 
]; 
let cars_s = cars.map(function(x) { 
    return x.id; 
}); 
let i = cars_s.indexOf(18); 
console.log(i); // 2 
console.log(cars[i]); // { id:18, make:'ford', color:'blue' } 

let index = {}; 
for (let i = 0; i < cars_s.length; i++) { 
    index[cars_s[i]] = i; 
} 
console.log(index[18]); // 2 
+0

очень круто! рад, что я спросил. Спасибо! – yevg

1

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

var cars_by_id = {}; 
cars.forEach(c => cars_by_id[c.id] = c); 

Теперь вы можете использовать cars_by_id[id], чтобы получить автомобиль, который Вы хотите.

Всякий раз, когда вы нажимаете на cars, вам также необходимо добавить к cars_by_id. Вы можете определить класс, который автоматизирует это.

+0

Вы избили меня на 2 секунды. :) –

+0

, но разве это просто переносит задачу обработки в другую форму? очевидно, итерации по всему объекту с помощью 'cars.forEach (c => cars_by_id [c.id] = c);' один раз намного лучше, чем делать это снова и снова при поиске, но это все равно может стать значительной производительностью если подсчет массива предметов находится в миллионах – yevg

+0

Это зависит от того, как часто вам нужно искать вещи. Если вы скрываете его в классе, вам никогда не нужно делать этот цикл, вы просто держите объект и массив в синхронизации с момента их создания. – Barmar

1

Построить объект, где каждый ключ является идентификатором объекта автомобиля и значение является сам объект автомобиля:

var cars = { 
    23: { id:23, make:'honda', color: 'green' }, 
    36: { id:36, make:'acura', color:'silver' }, 
    18: { id:18, make:'ford', color:'blue' }, 
    62: { id:62, make:'ford', color:'green' }, 
}; 

Это будет гораздо быстрее, чтобы получить доступ, как это:

console.log(cars[18].make); 
+0

это было бы идеально, но иногда было бы невозможно, так как данные могут поступать из моих источников. даже в простом случае, вызовы MySQL db обычно не возвращают данные в этом формате, а повторное форматирование, когда его полученный просто проходит вычислительную дилемму вверх по цепочке задач – yevg

Смежные вопросы