【问题标题】:A better way to search an object搜索对象的更好方法
【发布时间】:2017-01-17 01:34:34
【问题描述】:

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

例如:

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

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

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

【问题讨论】:

  • 不要在array上使用for ... in

标签: javascript arrays json object array-algorithms


【解决方案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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 你领先我 2 秒。 :)
    • 但这不只是将处理任务转移到另一种形式吗?显然,使用cars.forEach(c =&gt; cars_by_id[c.id] = c); 遍历整个对象一次要比在搜索时一遍又一遍地执行要好得多,但是如果主题数组的数量以百万计,这仍然会成为显着的性能负载
    • 这取决于您需要多久搜索一次。如果你把它隐藏在一个类中,你永远不需要做那个循环,你只需要从你创建对象和数组开始就保持同步。
    【解决方案3】:

    构造一个对象,其中每个键是汽车对象的 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);
    

    【讨论】:

    • 这将是理想的,但有时是不可行的,因为数据可能来自我无法控制的来源。即使在简单的情况下,MySQL db 调用也往往不会以这种格式返回数据,并且在收到数据时重新格式化只会将计算困境传递到任务链中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 2015-09-11
    • 2011-12-19
    • 2014-07-12
    • 1970-01-01
    相关资源
    最近更新 更多