用于快速查找和有序循环的 JavaScript 数据结构

发布于 2024-09-15 11:29:04 字数 148 浏览 8 评论 0原文

JavaScript 中是否有一种数据结构或模式可以用于快速查找(通过键,如关联数组)和有序循环?

是的,现在我使用对象文字来存储我的数据,但我刚刚发现 Chrome 在循环属性名称时不保持顺序。

JavaScript 有没有通用的方法来解决这个问题?

Is there a data structure or a pattern in JavaScript that can be used for both fast lookup (by key, as with associative arrays) and for ordered looping?

Right, now I am using object literals to store my data, but I just discovered that Chrome does not maintain the order when looping over the property names.

Is there a common way to solve this in JavaScript?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

江湖正好 2024-09-22 11:29:04

自己创建一个数据结构。将顺序存储在结构内部的数组中。将键映射的对象存储在常规对象中。我们将其称为 OrderedMap ,它将有一个映射、一个数组和四个基本方法。

OrderedMap
    map
    _array

    set(key, value)
    get(key)
    remove(key)
    forEach(fn)

function OrderedMap() {
    this.map = {};
    this._array = [];
}

插入元素时,将其添加到数组中所需的位置以及对象中。按索引插入或在末尾插入的时间复杂度为 O(1)。

OrderedMap.prototype.set = function(key, value) {
    // key already exists, replace value
    if(key in this.map) {
        this.map[key] = value;
    }
    // insert new key and value
    else {
        this._array.push(key);
        this.map[key] = value;
    }
};

删除对象时,将其从数组和对象中删除。如果按键或值删除,复杂度为 O(n),因为您需要遍历维持排序的内部数组。按索引删除时,复杂度为 O(1),因为您可以直接访问数组和对象中的值。

OrderedMap.prototype.remove = function(key) {
    var index = this._array.indexOf(key);
    if(index == -1) {
        throw new Error('key does not exist');
    }
    this._array.splice(index, 1);
    delete this.map[key];
};

查找的时间复杂度为 O(1)。通过键从关联数组(对象)中检索值。

OrderedMap.prototype.get = function(key) {
    return this.map[key];
};

遍历将是有序的并且可以使用任一方法。当需要有序遍历时,创建一个包含对象(仅值)的数组并返回它。作为一个数组,它不支持键控访问。另一种选择是要求客户端提供一个回调函数,该函数应应用于数组中的每个对象。

OrderedMap.prototype.forEach = function(f) {
    var key, value;
    for(var i = 0; i < this._array.length; i++) {
        key = this._array[i];
        value = this.map[key];
        f(key, value);
    }
};

请参阅 Closure 库中的 Google 实现 LinkedMap,了解相关文档和源代码这样的一堂课。

Create a data structure yourselves. Store the ordering in an array that is internal to the structure. Store the objects mapped by a key in a regular object. Let's call it OrderedMap which will have a map, an array, and four basic methods.

OrderedMap
    map
    _array

    set(key, value)
    get(key)
    remove(key)
    forEach(fn)

function OrderedMap() {
    this.map = {};
    this._array = [];
}

When inserting an element, add it to the array at the desired position as well as to the object. Insertion by index or at the end is in O(1).

OrderedMap.prototype.set = function(key, value) {
    // key already exists, replace value
    if(key in this.map) {
        this.map[key] = value;
    }
    // insert new key and value
    else {
        this._array.push(key);
        this.map[key] = value;
    }
};

When deleting an object, remove it from the array and the object. If deleting by a key or a value, complexity is O(n) since you will need to traverse the internal array that maintains ordering. When deleting by index, complexity is O(1) since you have direct access to the value in both the array and the object.

OrderedMap.prototype.remove = function(key) {
    var index = this._array.indexOf(key);
    if(index == -1) {
        throw new Error('key does not exist');
    }
    this._array.splice(index, 1);
    delete this.map[key];
};

Lookups will be in O(1). Retrieve the value by key from the associative array (object).

OrderedMap.prototype.get = function(key) {
    return this.map[key];
};

Traversal will be ordered and can use either of the approaches. When ordered traversal is required, create an array with the objects (values only) and return it. Being an array, it would not support keyed access. The other option is to ask the client to provide a callback function that should be applied to each object in the array.

OrderedMap.prototype.forEach = function(f) {
    var key, value;
    for(var i = 0; i < this._array.length; i++) {
        key = this._array[i];
        value = this.map[key];
        f(key, value);
    }
};

See Google's implementation of a LinkedMap from the Closure Library for documentation and source for such a class.

停顿的约定 2024-09-22 11:29:04

Chrome 不维护对象字面量中键的顺序的唯一情况似乎是键是数字。

  var properties = ["damsonplum", "9", "banana", "1", "apple", "cherry", "342"];
  var objLiteral = {
    damsonplum: new Date(),
    "9": "nine",
    banana: [1,2,3],
    "1": "one",
    apple: /.*/,
    cherry: {a: 3, b: true},
    "342": "three hundred forty-two"
  }
  function load() {
    var literalKeyOrder = [];
    for (var key in objLiteral) {
      literalKeyOrder.push(key);
    }

    var incremental = {};
    for (var i = 0, prop; prop = properties[i]; i++) {
      incremental[prop] = objLiteral[prop];
    }

    var incrementalKeyOrder = [];
    for (var key in incremental) {
      incrementalKeyOrder.push(key);
    }
    alert("Expected order: " + properties.join() +
          "\nKey order (literal): " + literalKeyOrder.join() +
          "\nKey order (incremental): " + incrementalKeyOrder.join());
  }

在 Chrome 中,上面的结果是:“1,9,342,damsonplum,banana,apple,cherry”。

在其他浏览器中,它会生成“damsonplum,9,banana,1,apple,cherry,342”。

因此,除非你的键是数字,否则我认为即使在 Chrome 中,你也是安全的。如果您的键是数字,也许只需在它们前面加上一个字符串即可。

The only instance in which Chrome doesn't maintain the order of keys in an object literal seems to be if the keys are numeric.

  var properties = ["damsonplum", "9", "banana", "1", "apple", "cherry", "342"];
  var objLiteral = {
    damsonplum: new Date(),
    "9": "nine",
    banana: [1,2,3],
    "1": "one",
    apple: /.*/,
    cherry: {a: 3, b: true},
    "342": "three hundred forty-two"
  }
  function load() {
    var literalKeyOrder = [];
    for (var key in objLiteral) {
      literalKeyOrder.push(key);
    }

    var incremental = {};
    for (var i = 0, prop; prop = properties[i]; i++) {
      incremental[prop] = objLiteral[prop];
    }

    var incrementalKeyOrder = [];
    for (var key in incremental) {
      incrementalKeyOrder.push(key);
    }
    alert("Expected order: " + properties.join() +
          "\nKey order (literal): " + literalKeyOrder.join() +
          "\nKey order (incremental): " + incrementalKeyOrder.join());
  }

In Chrome, the above produces: "1,9,342,damsonplum,banana,apple,cherry".

In other browsers, it produces "damsonplum,9,banana,1,apple,cherry,342".

So unless your keys are numeric, I think even in Chrome, you're safe. And if your keys are numeric, maybe just prepend them with a string.

将军与妓 2024-09-22 11:29:04

作为
已注明(如果您的键是数字)
您可以在它们前面添加一个字符串以保持顺序。

var qy = {
  _141: '256k AAC',
   _22: '720p H.264 192k AAC',
   _84: '720p 3D 192k AAC',
  _140: '128k AAC'
};

示例

As
has been noted, if your keys are numeric
you can prepend them with a string to preserve order.

var qy = {
  _141: '256k AAC',
   _22: '720p H.264 192k AAC',
   _84: '720p 3D 192k AAC',
  _140: '128k AAC'
};

Example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文