【问题标题】:Sort a JavaScript object by key or value; ES6按键或值对 JavaScript 对象进行排序; ES6
【发布时间】:2019-03-23 22:46:55
【问题描述】:

在我问之前;关于这个特定主题有很多讨论,其中大部分与 ES5 相关,不一定适用于 ES6。我试图得到一些澄清,也许可以帮助下一个在互联网上寻找答案的人。 这是专门针对 ES6 的

问题:

考虑以下对象结构:

const unsorted_object = {
    'C': '0003',
    'D': '0004',
    'A': '0001',
    'B': '0002',
    'F': '0005',
}; 
  1. 如何按键对 JavaScript 对象进行排序? (已回复here

    const sorted_object = {};
    Object.keys(unsorted_object).sort().forEach(function(key) {
        sorted_object[key] = unsorted_object[key];
    });
    
  2. 如何按键值对 JavaScript 对象进行排序?

编辑 #1

我可能对问题 #2 不太清楚。这个想法是通过键的值而不是键和值对 JavaScript 对象进行排序。

编辑#2

const unsorted_object = {
    '0001': '13.1666',
    '0002': '11.0001',
    '0003': '10.6664',
    '0004': '13.1666',
    '0005': '7.3331',
};

输出:

'0001': '13.1666'
'0004': '13.1666'
'0002': '11.0001'
'0003': '10.6664'
'0005': '7.3331'

【问题讨论】:

  • 为什么要对对象进行排序(它们在设计上是无序的)?你能解释一下你想要做什么的大局吗?
  • @JBallin 在 ES6+ 中,对象属性 有序的 - 它仅在 ES5 和之前它们没有定义的顺序。
  • @JBallin 我不同意。我觉得 2010 年提出的问题是在 ES5 的前提下回答的,因此不是 ES6 特有的。
  • @artomason 一些 answers 使用 ES6。如果你真的认为它不同,你应该将你的标题编辑为 ES6 特定的。

标签: javascript sorting object ecmascript-6


【解决方案1】:

ES6 中的对象键具有遍历顺序。整数键总是第一个,并按升序(0 -> 9)排序。在非整数键中,分配顺序被保留(参见article)。要对对象的键进行排序,我们需要重新创建对象,并按所需的顺序添加键。

注意:这意味着排序只会对非整数键起作用,因为整数总是排在第一位,并且总是按升序排序。

排序和重新创建对象:

const unsorted_object = {
    '0001': '13.1666',
    '0002': '11.0001',
    '0003': '10.6664',
    '0004': '13.1666',
    '0005': '7.3331',
};

const sorted_object = Object.entries(unsorted_object)
  .sort(([,v1], [,v2]) => +v2 - +v1)
  .reduce((r, [k, v]) => ({ ...r, [k]: v }), {});

console.log(sorted_object);

如果支持,您可以使用 Object.fromEntries() 而不是 Array.reduce() 从条目创建对象:

const unsorted_object = {
    '0001': '13.1666',
    '0002': '11.0001',
    '0003': '10.6664',
    '0004': '13.1666',
    '0005': '7.3331',
};

const sorted_object = Object.fromEntries(
  Object.entries(unsorted_object)
    .sort(([,v1], [,v2]) => +v2 - +v1)
);

console.log(sorted_object);

边缘友好版本,使用 Object.assign() 而不是传播:

const unsorted_object = {
    '0001': '13.1666',
    '0002': '11.0001',
    '0003': '10.6664',
    '0004': '13.1666',
    '0005': '7.3331',
};

const sorted_object = Object.entries(unsorted_object)
  .sort(([,v1], [,v2]) => +v2 - +v1)
  .reduce((r, [k, v]) => Object.assign(r, { [k]: v }), {});

console.log(sorted_object);

【讨论】:

  • 我是 JavaScript 的新手,您能否再详细说明一下您的答案。有一些我不明白的语法。例如,.sort(([,v1], [,v2]) =>...
  • 感谢您的更新。我仍在尝试更多地处理信息,但是是否可以使用相同的方法按降序(值)排序?你谈到了键,但我不确定这是否也适用于价值。
  • 您使用值对对进行排序,然后使用这些对按排序顺序重新创建对象。查看更新的答案(按值降序排列)。
  • 我无法让它正常工作,但我也注意到这实际上不是我想要的,我想哈哈。我正在寻找仅通过问题 #2 的值对对象进行排序。听起来我在要求关键和价值。我不确定你是否是这样解释的。
  • 它在 Firefox 上运行良好。 Edge 不支持对象扩展,因此我将其替换为 Object.assign。查看更新。
【解决方案2】:

提取entries而不是keys,然后通过每个值的差异提取sort

const unsorted_object = {
    'C': '0003',
    'D': '0004',
    'A': '0001',
    'B': '0002',
    'F': '0005',
};

const sorted_object = {};
Object.entries(unsorted_object)
  .sort((a, b) => a[1] - b[1])
  .forEach(([key, val]) => {
    sorted_object[key] = val;
  });
console.log(sorted_object);

请注意,使用reduce 从数组构造对象可能更合适:

const unsorted_object = {
    'C': '0003',
    'D': '0004',
    'A': '0001',
    'B': '0002',
    'F': '0005',
};

const sorted_object = Object.entries(unsorted_object)
  .sort((a, b) => a[1] - b[1])
  .reduce((a, [key, val]) => {
    a[key] = val;
    return a;
  }, {});
console.log(sorted_object);

【讨论】:

    【解决方案3】:

    您可以对entries 进行排序并使用reduce() 创建新对象。

    话虽如此,您的应用设计中可能存在问题,甚至需要执行此类操作

    const unsorted_object = {
      'C': '0003',
      'D': '0004',
      'A': '0001',
      'B': '0002',
      'F': '0005',
    };
    
    const sorted = Object.entries(unsorted_object)
      .sort((a, b) => a[1] - b[1])
      .reduce((a, c) => (a[c[0]] = c[1], a), {})
    
    console.log(sorted)

    【讨论】:

    • 我不知道为什么这被否决了,一些见解会很好。
    • @artomason 有人很快通过并否决了所有最初的答案。它发生了......对此无能为力。如果您认为这是错误的,您有权投票