【问题标题】:How to sort an array where the keys are numeric strings如何对键是数字字符串的数组进行排序
【发布时间】:2019-11-08 02:02:42
【问题描述】:

我需要创建一个对象,其中键是由数字组成的字符串,但我无法以正确的方式对它们进行排序:

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)
}

我想要的输出是:00、11、22、33。

但它会重现:11、22、33、00。

我已经尝试使用 Object.keys 对这个对象进行排序,但是当我在其上设置迭代器时,值“00”总是到最后。

【问题讨论】:

标签: javascript


【解决方案1】:

你不能依赖你所说的使用for-in 循环的输出。尽管对象属性在 ES2015 中具有顺序,但 for-in 循环不要。 (Object.keys 的数组也没有。)

如果你想要顺序,你想要一个数组。 (但在某些情况下,您也可以使用Map;见下文。)

此外,即使使用 ES2015 的属性顺序,您显示的键也永远不会按照您显示的顺序,因为 '00''11''22''33' 不同:不是canonical number String。 ES2015 顺序(对于支持它的操作)是名称为规范数字字符串格式的字符串的属性,按数字顺序排列,然后是其他以字符串命名的属性(按添加顺序),然​​后是以符号命名的属性。

因此,您的对象永远不会按照您所说的那样运行。使用数组。

(当然,如果你引入一个前缀,所以它们都不是规范数字字符串格式,并按照你想要的顺序添加属性,这将适用于Object.getOwnPropertyNames和其他支持该顺序的操作。但我真的不会那样做。)

另一种选择是使用Map,它与对象不同始终遵循键的首次使用顺序。¹如果您像这样创建Map

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

...然后遍历该映射将可靠地访问 '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);
}

¹这是简单的版本。更长的版本:如果您向映射添加键/值并且该键尚未在映射中,则它位于映射键列表的末尾。如果您为该键设置了一个新值,它不会在该列表中移动。如果您删除密钥,然后再添加它,它会再次出现在最后。

【讨论】:

    【解决方案2】:

    当涉及到它们的键时,对象没有排序的概念。即使您可以在特定浏览器中使用此特定数据集实现此目的,也不能保证密钥会按照您想要的顺序出现。

    如果您真的想实现这一点,您应该对从Object.keys() 返回的键进行排序并对其进行迭代。


    我上面的原始答案不正确。 As of ES2015,对象键确实有特定的顺序。我仍然认为尝试依赖对象的键顺序可能是一个坏主意 - 使用 Map 来保留键的原始值(而不会将它们强制为字符串)并在迭代时对键进行排序。

    【讨论】:

    • 啊,这是新的-我刚刚找到this的答案,这反驳了我的答案。
    • ES6 并不是全新的,但我知道 90% 的 SO 仍然相信 ES5 规范。提出有关对象属性顺序的问题,您将在第一分钟内得到一个“没有”的答案。无论如何,这样可能更好——那么至少不会有 392454 人在愚蠢的情况下使用财产订单:)
    • 它太新了,以至于我不知道规范的这个非常具体的细节。它不像有很多关于它的宣传。我很高兴修改我的答案(我必须)准确无误。
    • @DanPantry - 取决于你在哪里闲逛。 :-) herehere 有不少。
    【解决方案3】:

    由于 ES2015 对象键确实有 traversal order

    • 合法数字(整数索引)的字符串排在第一位,并按其值排序
    • 未放在数字字符串之后的字符串,其顺序由输入顺序定义

    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)
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-18
      • 1970-01-01
      • 2021-08-17
      • 2017-07-13
      相关资源
      最近更新 更多