简体   繁体   English

如何对键是数字字符串的数组进行排序

[英]How to sort an array where the keys are numeric strings

I need to create one Object where the keys are strings composed of numbers but I couldn't sort them in the correct way:我需要创建一个 Object ,其中键是由数字组成的字符串,但我无法以正确的方式对它们进行排序:

 let simple_arr = ['00', '11', '22', '33']; let simple_obj = {}; for (let it of simple_arr) { simple_obj[it] = "anything"; } for (let it2 in simple_obj) { console.log(it2) }

The output that I would like is: 00, 11, 22, 33.我想要的 output 是:00、11、22、33。

But it reproduces: 11, 22, 33, 00.但它重现:11、22、33、00。

I already tried to sort this object with Object.keys, but always when I set an iterator on it the value "00" goes to the end.我已经尝试用 Object.keys 对这个 object 进行排序,但是当我在它上面设置一个迭代器时,值“00”总是到最后。

You cannot rely on the output you've said you want using a for-in loop.您不能依赖您说过要使用for-in循环的 output。 Although object properties have order as of ES2015, for-in loops don't .尽管 object 属性在 ES2015 中具有顺序,但for-in循环没有 (Neither does the array from Object.keys .) Object.keys中的数组也没有。)

If you want order, you want an array.如果你想要订单,你想要一个数组。 (But you can use a Map , too, in some situations; see below.) (但在某些情况下,您也可以使用Map ;见下文。)

Moreover, even with ES2015's property order, the keys you've shown will never be in the order you've shown, because '00' is different from '11' , '22' , and '33' : It's not a canonical number String .此外,即使使用 ES2015 的属性顺序,您显示的键也永远不会按照您显示的顺序,因为'00''11''22''33'不同:它不是规范数字字符串 The ES2015 order (for the operations that support it) is properties whose names are strings in canonical number String format, in order numerically, followed by other string-named properties in the order they were added, followed by Symbol-named properties. ES2015 顺序(对于支持它的操作)是名称为规范数字字符串格式的字符串的属性,按数字顺序排列,然后是其他以字符串命名的属性(按照它们添加的顺序),然后是符号命名的属性。

So your object will never behave as you've said you want.因此,您的 object 永远不会像您所说的那样运行。 Use an array.使用数组。

(Of course, if you introduce a prefix so none of them is in canonical number String format and add the properties in the order you want them, that would work with Object.getOwnPropertyNames and other operations that support the order. But I really wouldn't do that.) (当然,如果您引入一个前缀,因此它们都不是规范数字字符串格式并按您想要的顺序添加属性,这将与Object.getOwnPropertyNames和其他支持该顺序的操作一起使用。但我真的不会不要那样做。)

Another option is to use a Map , which unlike objects always follows the order that the keys were first used.¹ If you create a Map like this:另一种选择是使用Map ,与对象不同,它始终遵循密钥首次使用的顺序。¹如果您像这样创建Map

const map = new Map(simple_arr.map(key => [key, "anything"]));

...then looping through that map will reliably visit the '00' entry, then the '11' entry, then the '22' entry, then the '33' entry: ...然后循环通过该 map 将可靠地访问'00'条目,然后是'11'条目,然后是'22'条目,然后是'33'条目:

 const simple_arr = ['00', '11', '22', '33']; const map = new Map(simple_arr.map(key => [key, "anything"])); for (const [key, value] of map.entries()) { console.log(key, value); }


¹ That's the simple version. ¹这是简单的版本。 The longer version: If you add a key/value to the map and that key is not already in the map, it goes at the end of the list of the map's keys.更长的版本:如果您将键/值添加到 map 并且该键不在 map 中,则它位于地图键列表的末尾。 If you set a new value for that key, it doesn't move in that list.如果您为该键设置了一个新值,它不会在该列表中移动。 If you remove the key and then add it again later, it goes at the end again.如果您删除密钥,然后再添加它,它会再次出现在最后。

Objects have no concept of ordering when it comes to their keys.当涉及到它们的键时,对象没有排序的概念。 Even if you could achieve this with this particular data set in your particular browser, there's no guarantee the keys will come out in the order you want.即使您可以在特定浏览器中使用此特定数据集实现此目的,也不能保证密钥会按照您想要的顺序出现。

If you really want to achieve this, you should sort the keys returned from Object.keys() and iterate over that.如果你真的想实现这一点,你应该对从Object.keys()返回的键进行排序并对其进行迭代。


My original answer above is incorrect.我上面的原始答案是不正确的。 As of ES2015 , object keys do have a specific order. 从 ES2015 开始,object 密钥确实有特定的顺序。 I still maintain that trying to rely on the order of keys of an object is probably a bad idea - Use a Map to retain the original values of your keys (without them being coerced to a string) and order the keys when iterating, instead.我仍然认为,尝试依赖 object 的键顺序可能是个坏主意 - 使用 Map 保留键的原始值(而不会将它们强制为字符串)并在迭代时对键进行排序。

Since ES2015 object keys do have a traversal order :由于 ES2015 object 键确实有遍历顺序

  • Strings that are legitimate numbers (Integer indices) come first, and ordered by their value合法数字(整数索引)的字符串排在第一位,并按其值排序
  • Strings that aren't are placed after numeric strings, and their order is defined by the order of entry没有放在数字字符串之后的字符串,它们的顺序由输入的顺序定义

Convert 00 to 0 so it will be ordered by the numeric value:00转换为0 ,使其按数值排序:

 const simple_arr = ['0', '11', '22', '33']; const simple_obj = {}; for(let it of simple_arr){ simple_obj[it] = "anything"; } for(let it2 in simple_obj){ console.log(it2) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM