【问题标题】:Iterating over JS Object across multiple arrays - Performance跨多个数组迭代 JS 对象 - 性能
【发布时间】:2015-01-20 15:41:24
【问题描述】:

所以基本上我在这里要做的是:

假设你有这个对象:

{
 owner: 'Richard',
 time: 141381983181,
 type: 'Football',
 approved:['Higgs','Rooney','Jake'],
 pending:['Richmond','Sarah','Evelyin'],
 rejected:['Bilbo','Alice','Marta']
}

现在,我需要一个快速函数来返回哪个“名称”属于哪个字段。

例如:determineUserLevel('Bilbo',aMeeting) //return rejected.

所以我写了一个:

function determineUserLevel(spec){

    var event = spec.event,
        user = spec.user;


    if(event.owner === user) return 'owner';

    for(var i = 0 ; i < event.approved.length; i++){

       if(event.approved[i] === user) return 'approved';

    }
    for(var x = 0; x < event.pending.length; x++){

        if(event.pending[x] === user) return 'pending';

    }
    for(var f = 0; f < event.rejected.length; f++){

        if(event.rejected[f] === user) return 'rejected'

    }

    return 'user';

}

有没有更好的方法?性能明智?可维护的明智?或者这是相当可靠的?

谢谢。

【问题讨论】:

  • 这个问题属于codereview.stackexchange.com,如果它有效并且您需要更好的方法。
  • 如果您调用该函数的示例实际上与您的函数的签名匹配,那将会很有帮助。我假设您实际上是这样称呼它的:determineUserLevel({event:aMeeting, user:"Bilbo"});
  • @MattBurland 跟我想的一样。
  • 除非您的列表已排序,否则线性搜索是您能做的最好的。除非您将数组转换为字典/哈希集,否则如果它们很大和/或您正在进行大量查找,这可能很有用。
  • @MattBurland 列表已排序是什么意思?

标签: javascript


【解决方案1】:

除非您的数组很大(数千个项目),否则这样的函数对性能的影响可以忽略不计。相反,您应该针对可靠性和可读性进行优化。

function determineUserLevel(spec){

    var event = spec.event,
        user = spec.user;


    if(event.owner === user) {
      return 'owner';
    }
    if(event.approved.indexOf(user) > -1) {
      return 'approved';
    }
    if(event.pending.indexOf(user) > -1) {
      return 'pending';
    }
    if(event.rejected.indexOf(user) > -1) {
      return 'rejected';
    }

    return 'user';

}

使用 indexOf 而不是循环可以简化代码并将循环条件输入错误的可能性降到最低。您也可以将两者结合起来以获得更高的可读性。

function determineUserLevel(spec){

    var event = spec.event,
        user = spec.user;


    if(event.owner === user) {
      return 'owner';
    }
    var sets = ['approved','pending','rejected'];

    for(var i=0; i<sets.length; i++) {
       var set = sets[i];
       if(event[set].indexOf(user) > -1) {
         return set
       }
    }

    return 'user';

}

它的可读性是一个判断要求,但它可以让您轻松扩展到更多集合,而无需重复自己。

【讨论】:

  • 然而这几乎没有什么不同。我希望有类似并行搜索的东西,想象一个用户被拒绝了,我们必须遍历所有领域才能意识到这一点,你不觉得吗?我的意思是,这甚至可能吗?
  • @Linial: Javascript 是单线程的(除非你想和网络工作者混在一起,我猜),但除非你已经确定这是你的应用程序中的一个实际瓶颈,否则我不会打扰它。
  • 非常感谢您的帮助@MattBurland,嗯,我有点相信这会成为未来的瓶颈
  • @Linial 你的数据集有多大?除非您在每个列表中迭代数千个项目,否则这不会很慢。
  • 每个数组将包含 20 个字符串。将来虽然这些会成为对象,但这会影响性能吗?
【解决方案2】:

将对象用作哈希集而不是字符串数组。所以不要这样:

approved:['Higgs','Rooney','Jake']

改成这样:

approved:{'Higgs':true,'Rooney':true,'Jake':true},

现在查找速度超级快:

if (approved[nameToTest]) {
    return "approved";
}

显然所有其他数组属性都是一样的。

如果你从一个数组开始,那么将它转换成一个哈希集是相当简单的,比如:

approved = ['Higgs', 'Rooney', 'Jake'];

var approvedObj = approved.reduce(function(curr, next) {
  curr[next] = true;
  return curr;
}, {});

alert(JSON.stringify(approvedObj));

转换的初始成本是否值得取决于您的收藏有多大以及您需要多久进行一次查找。

【讨论】:

  • 采集约10000个“Events || Meetings”,查找约5000次/分钟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2018-06-30
  • 2010-10-03
  • 2011-01-12
  • 2018-03-01
  • 1970-01-01
相关资源
最近更新 更多