如何在保持键查找的同时保持 Javascript 对象/数组的有序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5773950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:46:58  来源:igfitidea点击:

How to keep an Javascript object/array ordered while also maintaining key lookups?

javascriptdata-structures

提问by DisgruntledGoat

I have some data which I originally stored in a generic Javascript object, with the ID as a key:

我有一些最初存储在通用 Javascript 对象中的数据,以 ID 作为键:

{
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}

However, I discovered that browsers do not guarantee a particular object order when looping through them, so in the above "3" would come before "7". I switched to using an array format like this:

但是,我发现浏览器在遍历它们时不保证特定的对象顺序,因此在上面的“3”中会出现在“7”之前。我改用这样的数组格式:

[
  {"id":"7","name":"Hello"},
  {"id":"3","name":"World"},
  ...
]

Now, I can loop in the correct order but cannot do fast lookups, e.g. data["3"]without having to loop through the array.

现在,我可以按正确的顺序循环,但不能进行快速查找,例如data["3"]无需遍历数组。

Is there a good way to combine both approaches? I would rather avoid using a separate object for each format, because the object is pretty large (hundreds of elements).

有没有结合这两种方法的好方法?我宁愿避免为每种格式使用单独的对象,因为该对象非常大(数百个元素)。

回答by Halcyon

I have run across this problem as well. A solution is to keep an ordered array of keys in addition to the original object.

我也遇到过这个问题。一个解决方案是在原始对象之外保留一个有序的键数组。

var objects = {
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}
var order = [ "3", "7", ... ];

Now if you want the second element you can do this lookup:

现在,如果您想要第二个元素,您可以进行以下查找:

var second_object = objects[order[1]];

The ECMA standard does not say anything about the order of the elements in an object. And specifically Chrome reorders the keys when they look likenumbers. Example:

ECMA 标准没有说明对象中元素的顺序。特别是当键看起来像数字时,Chrome 会重新排序。例子:

var example = {
    "a": "a",
    "b": "b",
    "1": "1",
    "2": "2"
};

if you print this in Chrome will get something like:

如果你在 Chrome 中打印它会得到类似的东西:

{
    1: "1",
    2: "2",
    "a": "a",
    "b": "b"
};

It's a little sour .. but life.

这有点酸..但生活。

You could use the solution Andy linked as well, basically wrapping these two together in one object.

您也可以使用 Andy 链接的解决方案,基本上将这两者包装在一个对象中。

An alternative that I use a lot is a custom map function that allows you to specify the order in which the object is traversed. Typically you will do sorting when you're printing your data to the user so while you loop and create your table rows (for instance) your iterator will pass the rows in the order your sort function specifies. I thought it was a nice idea :)

我经常使用的另一种方法是自定义映射函数,它允许您指定遍历对象的顺序。通常,您将在向用户打印数据时进行排序,因此在循环和创建表行(例如)时,迭代器将按照排序函数指定的顺序传递行。我认为这是个好主意:)

The signature looks like:

签名看起来像:

function map(object, callback, sort_function);

Example usage:

用法示例:

map(object, function (row) {
   table.add_row(row.header, row.value);
}, function (key1, key2) {
   return object[key1] - object[key2];
});