【问题标题】:javascript / jQuery: most efficient way to search in and update an Array of Objectsjavascript / jQuery:搜索和更新对象数组的最有效方法
【发布时间】:2014-10-31 22:07:37
【问题描述】:

我目前正在从事一个私人方面/有趣的项目,这是一个基于javascriptjQuery 的小型浏览器游戏。

对于这个游戏,我将数据保存到对象数组中:

this.map.push(
    { 
        "id" : id, 
        "x" : pos_x,
        "y" : pos_y
    }
);

现在我需要非常频繁地(“实时”)查找和/或更新此数组中的数据。

例如,当我需要在我的坐标系统的某个位置找到数组索引时,我正在使用jQuery$.each() 函数:

this.getIndexAtPos = function(x, y)
{
    var index = false;
    $.each(this.map, function(key, obj){
        if(obj.x == x && obj.y == y)
        {
            index = key;
            return false;
        }
    });
    return index;
}


另一个例子:当我需要更新具有特定 id 的对象的数据时,我使用jQuery$.map() 函数:

this.updateCoordsById = function(id, x, y)
{
    this.map = $.map(this.map, function(obj, i)
    {
        if(obj.id == id)
        {
            //only update x, y!
            obj.x = x;
            obj.y = y;
            return obj;
        }
        else
        {
            return obj;
        }
    });
}

到目前为止,这一切对我来说都很好,但是我在一台相当快的计算机上,随着游戏的扩展,这些动作将会越来越多。比如说每秒有几百个$.each$.map 调用。
这就是为什么我担心性能问题,尤其是在速度较慢的计算机上。


我的问题: 我知道$.each$.map 在每次调用时(部分或全部)迭代我的数组。这就是为什么我一发现条目就在我的$.each 函数中使用return false; 以加快速度。

1.我可以通过使用其他jQuery函数或改变我使用它们的方式来提高性能吗?
2.有没有更好的方法(性能wise) 使用本机javascript 来解决这个问题?
3.我应该使用其他数据类型/结构来提高性能吗?

注意: 我需要实现的过程总是非常相似:通过 coords(x, y) 在数组中查找对象;通过 id 找到它们;通过 coords(x, y) 更新对象;按 id 更新对象,等等。


我将不胜感激任何帮助、意见和建议!

【问题讨论】:

  • 我认为这归结于你的数据结构,而不是你用来访问它的函数。我是否正确假设您的地图是(希望是矩形的)网格 i 宽且 j 高,并且在任何时候都只能在 (x,y) 处有一个对象?
  • @Rhumborl 是的,没错。
  • 1 - 没有。 2 - 是(原生 JS 总是比 jQuery 快)。 3 - 是的,当然。你能想到吗?
  • @Bergi 我喜欢“否/是”的答案,它们很有建设性。
  • 是的,用于高效按位置查找的对象的二维数组和将 id 映射到用于高效按 id 查找的对象的对象会做得更好。试试看!

标签: javascript jquery arrays json performance


【解决方案1】:

好的,因为这是一个网格,所以将它作为一个网格存储在内存中是有意义的。 二维数组将比一维数组提供更快的访问速度,还可以让您直接通过坐标访问对象,而不是检查每个对象的坐标。

您还可以拥有一个包含所有对象的容器对象,并将其 ID 作为属性,这样您就可以通过 ID 快速查找。

您可以通过将对象的 ID 存储在网格中,然后通过 ID 在容器中查找对象来将这些放在一起。

我在http://jsfiddle.net/d75zkvnb/1/ 创建了一个小提琴,它显示了一个简单的例子。 Map 对象的结构如下:

var Map = {
    init: function(){
        this.Width = 10;
        this.Height = 10;

        // grid stores the coordinates and the IDs of the object at that coordinate
        // note this is stored by y then x.
        this.grid = [];
        // stored the actual objects, indexed by id
        this.objects = {};

        // set up the grid        
        for(var y = 0; y < this.Height; ++y)
        {
            this.grid.push(new Array(this.Width));
        }    
    },

    // gets the object at (x, y)
    GetAtCoord: function(x, y)
    {
        // find the id
        var id = this.grid[y][x];
        // directly access it from the array
        return this.objects[id];
    },

    // gets the object with the ID
    GetById: function(objId)
    {
        // direct access to the object
        return this.objects[objId];
    },

    // add an object at its stored coordinates
    AddObject: function(obj){
        this.grid[obj.y][obj.x] = obj.id;
        this.objects[obj.id] = obj;
    },

    // Move an object in the grid
    MoveObject: function(objId, newX, newY)
    {
        // get the objct to move
        var theObj = this.objects[objId];
        // reove it from the grid
        this.grid[theObj.y][theObj.x] = null;
        // updates its stored position
        theObj.x = newX;
        theObj.y = newY;

        // add it back to the grid
        this.grid[newY][newX] = objId;
    }
};

【讨论】:

  • 哇,非常感谢您的努力! - 我会试试这个。另外我还想知道-1
  • 这取决于您希望如何将坐标存储在实际对象中。数组从 0 开始,但某些坐标系从 1 开始,因此您必须进行调整。如果您可以将它们从 0 开始存储在您的对象中,那么只需取出 -1。
  • 刚刚找到你-1的原因:for(var y = 0; y &lt; this.Height; ++y )。如果你把它改成y++,你就不需要-1
  • @Rhumborl 好吧,除了 MS Access 中的数组之外,几乎所有东西都从 0 开始:D
  • 您的代码的另一个问题:我想没有办法以这种方式继承或扩展Map - 或者有吗?
猜你喜欢
  • 2011-06-06
  • 1970-01-01
  • 2016-08-14
  • 2012-06-03
  • 2014-05-24
  • 1970-01-01
  • 1970-01-01
  • 2021-10-08
  • 2015-01-01
相关资源
最近更新 更多