【问题标题】:Reverse object with Object.keys and Array.reverse [duplicate]使用 Object.keys 和 Array.reverse 反转对象 [重复]
【发布时间】:2018-01-18 13:37:35
【问题描述】:

我得到了以下对象

{
  "20170007": {
    "id": 1
  },
  "20170008": {
    "id" : 2
  },
  "20170009": {
   "id": 3
  },
  "20170010": {
    "id": 4
  }
}

想要的输出:

{
  "20170010": {
    "id": 4
  },
  "20170009": {
   "id": 3
  },
  "20170008": {
    "id" : 2
  },
  "20170007": {
    "id": 1
  }
}

我的尝试:

const obj = {
  "20170007": {
    "id": 1
  },
  "20170008": {
    "id" : 2
  },
  "20170009": {
   "id": 3
  },
  "20170010": {
    "id": 4
  }
}

const reverseObj = (obj) => {
  let newObj = {}

  Object.keys(obj)
    .sort()
    .reverse()
    .forEach((key) => {
      console.log(key)
      newObj[key] = obj[key]
    })

  console.log(newObj)
  return newObj  
}

reverseObj(obj)

奇怪的是,当我在 forEach 中使用 console.log 键时,键是相反的。但是当我将密钥分配给 newObj 时,输出仍然是原始顺序...... 这是怎么回事?

编辑:

感谢我查看地图对象的所有回复。 Map

new Map([iterable])

这实际上是我正在寻找的,并且订单是有保证的。

【问题讨论】:

  • 与数组不同,对象不保证键的存储顺序。您应该阅读以下内容:stackoverflow.com/questions/5525795/…
  • 如果你想订购...使用数组
  • 你是如何使用地图的?我现在确实遇到了这个问题

标签: javascript ecmascript-6


【解决方案1】:

对象的元素没有顺序

如果你想让它们有顺序,你应该将元素存储在一个数组中。

const obj = {
  "20170007": {
    "id": 1
  },
  "20170008": {
    "id" : 2
  },
  "20170009": {
   "id": 3
  },
  "20170010": {
    "id": 4
  }
}

const arrayReverseObj = (obj) => {
  let newArray = []

  Object.keys(obj)
    .sort()
    .reverse()
    .forEach(key => {
      console.log(key)
      newArray.push( {
      'key':key, 
      'id':obj[key].id
      })
    })

  console.log(newArray)
  return newArray  
}

arrayReverseObj(obj)

结果和你想要的差不多,但是是一个数组(这样元素可以有顺序):

[{ “关键”:“20170010”, “身份证”:4 }, { “关键”:“20170009”, “身份证”:3 }, { “关键”:“20170008”, “身份证”:2 }, { “关键”:“20170007”, “身份证”:1 }]

更简洁,使用 .map

我们可以使用.map(),而不是完全镜像您的代码布局,如下面的评论所示。一个例子是:

const arrayReverseObj = 
  obj => Object.keys(obj).sort().reverse().map(key=> ({key:key,id:obj[key].id}) );

如果您想要每个子对象的整体,而不仅仅是 `id` 属性

正如在下面的进一步评论中指出的那样,

const arrayReverseObj = 
  obj => Object.keys(obj).sort().reverse().map(key=> ({...obj[key],key:key}) );

这将返回一个对象数组,按其键的反向排序顺序,并且每个对象都有一个额外的属性key 包含它们的键。

一般来说,对于任何对象o{... o } 构造是创建一个新对象,由o 的所有属性组成,即o 的一种副本。 {... o, foo:"bar" } 做同样的事情,但添加了一个新属性 foo,其值为“bar”。

因此,我们解绑(“解构”)原始子对象,合并到一个新属性key,然后将其重新捆绑为一个与原始对象类似但具有额外属性的新对象。

这实现了与Object.assign 相同的效果,但它是声明式(函数式)而不是命令式(过程式),这使其更易于阅读。

评论者还建议的另一个简写是,当您使用{ a: 1, b: "hello", c: c } 之类的表达式构建对象时,如果属性c 的值被设置为也称为@987654336 的变量@,你可以跳过: c,Javascript 会假设你的意思是c: c。因此它节省了写{ a: 1, b: "hello", c }的空间。

所以我们的语句会变成:

const arrayReverseObj = 
  obj => Object.keys(obj).sort().reverse().map(key=> ({ ...obj[key], key }) );

【讨论】:

  • 我想你在找map
  • 我正在查看一个 JSON 响应,其中包含一个对象列出键(与页面元素相关),按它们在页面上出现的顺序排列。这怎么不是有序对象?
  • 如果您需要一个对象的数组,其顺序与原始键相反,则不需要sort。此外,如果您不仅想要 id,还想要整个原始对象以及密钥,您可以执行 const arrayReverseObj = (obj) => Object.keys(obj).reverse().map(key => ({ ...obj[key], key, }));
【解决方案2】:

对象是对象类型的成员。 这是一个无序的 属性集合,每个属性都包含一个原始值, 对象或功能。存储在对象属性中的函数是 称为方法。

ECMA specification

由于对象是无序的,你应该使用数组来代替。

【讨论】:

  • 您引用一个已有近 20 年历史的规范有什么原因吗?
  • @torazaburo 可能是因为最新的规范版本不再包含该特定措辞
猜你喜欢
  • 2022-11-14
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多