搜索对象的更好方法

A better way to search an object

我经常会发现自己必须从一个对象或一组由任意索引索引的对象访问特定对象,但我需要的对象是其键与特定值匹配的对象。

例如:

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' }

但这看起来很麻烦,而且随着性能的变化,扩展性也很差。来自大型数据集的值可能会很快返回,如果它朝向数组的开头,或者在最坏的情况下,将进行与条目数一样多的迭代。 如果该值根本不存在,这似乎也非常浪费,因为您只是迭代了所有对象只是为了得到一个空结果。

当搜索条件与主题键的参数不同时,是否有更优雅的方法来搜索数组或对象的值?

创建一个对象,其键是您希望能够搜索的属性:

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

现在您可以使用 cars_by_id[id] 获得您想要的汽车。

每当您推送到 cars 时,您还需要添加到 cars_by_id。您可能想要定义一个 class 来自动执行此操作。

构造一个对象,其中每个键是汽车对象的id,值是汽车对象本身:

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);

你可以使用Array.prototype.map()创建一个影子数组,这样可以帮助你更快地搜索,或者你也可以像下面这样创建一个index对象,它会直接return 你需要的索引。

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