【问题标题】:Lookup function or for in loop?查找函数还是for循环?
【发布时间】:2016-08-05 01:10:13
【问题描述】:

哪一个对性能更好 - 具有查找函数以查找具有特定 ID 的数组中的对象或仅使用 for in 循环与数组中的孔?

在我的情况下,我的玩家数组是动态的。假设连接了 3 个玩家,所以我的数组如下所示:

players = [player1, player2, player3]

将数组键作为玩家 ID 很容易,所以我会知道 ID 为 2 的玩家在玩家数组中排名第三,为了访问他,我只需要使用:players[2],但随着第二个玩家离开他创建一个数组孔:

players = [player1,,player3]

据我所知,这个洞会降低使用数组的性能,因为我经常使用 for-in 循环,所以拥有一个播放器对象数组而不是留下数组洞我只是拼接出洞?但是这样我就不能将数组键作为玩家 ID,所以我必须使用 ID 查找功能。那么到底这两种选择中哪一种对性能更好呢?或者有更好的方法来解决这个问题?

谢谢!

【问题讨论】:

  • 对于包含 2 个(或 200 或 2000 个)元素的数组,这并不重要。
  • 为什么不使用属性键是玩家 ID 的 javascript 对象{}
  • "程序员浪费大量时间去思考或担心程序中非关键部分的速度,而在考虑调试和维护时,这些效率上的尝试实际上会产生强烈的负面影响。我们应该忘记小的效率,比如说大约 97% 的时间:过早的优化是万恶之源。但我们不应该放弃关键的 3% 的机会” Donald Knuth
  • 我认为这是一个很好的问题。因为这不仅仅是关于性能。如果像这样实现,迟早你必须进行清理,删除所有漏洞并重新分配 ID,否则数组会变得太大。

标签: javascript arrays performance


【解决方案1】:

在我看来,@Jaromanda X 在 cmets 中提到的选项是最好的,因为“洞实现”会变得越来越慢,尤其是在遍历玩家数组时,因为当你不断添加和删除玩家时,箭头生长并变得非常稀疏,主要由孔组成。

var players = {};
players[p.id] = p; // add player p
delete players[p.id]; // remove player p
// player ids have to be unique and should be strings

这就是为什么查找不是一个好主意的原因,首先我认为这可能很容易,但实际上这段代码失败了,因为您必须在删除播放器后更新所有索引.. . 所以最好使用玩家对象。

// ATTENTION: example of FAILING implementation
var players = [];
var map = {};
// add player p
var idx = players.push(p) - 1;
map[p.id] = idx;
// remove player p
players.splice(map[p.id], 1);
delete map[p.id];

【讨论】:

  • 内存泄漏?怎么样?
  • 如果他不断添加和删除玩家,数组会不断增长,变得非常稀疏。
  • 这不是内存泄漏(同样window.foo = 'bar'; 不是内存泄漏)。 JS 中不能有内存泄漏(除非实现中存在错误)。您所指的只是低效的内存使用。
  • 在现实生活中“将变得越来越慢”可以忽略不计也是有道理的(除非 OP 正在做一些疯狂的事情,这不太可能)
  • 如果游戏有一个主大厅,有人在第二个进出,那么这并不疯狂。
【解决方案2】:

使用

var players = {
    abc1: player1,
    abc2: player2, 
    abc3: player3
}

而不是var players = [player1, player2, player3]

现在您可以通过players.abc1.name = "Nicholas" 访问它,无需查找功能。如果您只是使用 ID 以有组织的方式查找每个玩家,我会推荐一种更简单的方法:

var players = {
    player1: player1,
    player2: player2,
    player3: player3
}

这样您可以更轻松地访问它,例如players.player1[madeUpPropName] = someValue;

另外,你永远不应该在数组上使用 for-in 循环。使用 forEach 或基本的 for 循环。 Why is using "for...in" with array iteration a bad idea?

【讨论】:

    【解决方案3】:

    您可以使用console.time(str)console.timeEnd(str) 自己轻松检查性能。使用以下示例进行检查:

    var array = ['player1', 'player2', 'player3'];
    
    // Test using indexOf
    console.time('test1');
    var val = array.indexOf('player3');
    console.timeEnd('test1');
    
    // Test using a for loop
    console.time('test2');
    for (var i in array) {
        if (i == 'player3') {
            break;
        }
    }
    console.timeEnd('test2');
    

    注意timetimeEnd 中的字符串如何匹配。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-07
      • 2016-05-25
      • 1970-01-01
      • 2018-06-26
      • 2016-06-20
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多