有没有办法在JavaScript对象中对键进行排序/排序?

Hoa*_*Hoa 63 javascript

例如以下内容

var data = {
    'States': ['NSW', 'VIC'],
    'Countries': ['GBR', 'AUS'],
    'Capitals': ['SYD', 'MEL']
}
for (var item in data) {
    console.log(item);
}
Run Code Online (Sandbox Code Playgroud)

版画

States
Countries
Capitals
Run Code Online (Sandbox Code Playgroud)

有没有办法按字母顺序排序,以便打印

Capitals
Countries
States
Run Code Online (Sandbox Code Playgroud)

小智 109

不在对象本身内:对象的属性集合是无序的.

您可以做的一件事是使用Object.keys(),并对Array进行排序,然后迭代它.

Object.keys(data)
      .sort()
      .forEach(function(v, i) {
          console.log(v, data[v]);
       });
Run Code Online (Sandbox Code Playgroud)

不支持ECMAScript第5版的浏览器的补丁(实现):

  • @CharlesJaimet:不确定你的意思是`.replace()`.你的意思是`.reverse()`?这确实可以使用,但只有当你想要逆转当前订单时.如果要反转排序的顺序,则必须先对其进行排序.`.sort()`方法确实接受了一个函数,但`.reverse()`却没有. (3认同)
  • @WillCarron:这是当前迭代的数字索引。因此,如果有 3 个键,则在每次调用回调时都会为 i 提供 0 、 1 、 2 。因为 `i` 没有在函数中使用,所以可以安全地移除它,因为 JS 从不要求你为所有或任何传递的参数提供参数。使用浏览器中可用的日志记录工具,您可以检查应用程序中数据的值。`console.log("'i' 的值为:", i)` (2认同)

pro*_*ype 13

就在这里.不在ECMAScript标准内,但跨浏览器和Node.js支持,并且显然稳定.请参阅/sf/answers/1624146681/.

编辑:这将返回一个订购密钥的对象.您可以使用Object.keys(...)从对象获取有序键.

为什么担心对象键顺序?差异在某些应用程序中很重要,例如使用xml2js解析XML,它将 XML表示为嵌套对象,并使用XML标记作为哈希键.

有几个笔记:

  • 看起来像整数的键首先出现并按数字顺序出现.
  • 看起来像字符串的键出现在下一个和按插入顺序.
  • 此订单由报告 Object.keys(obj)
  • 报告的顺序for (var key in obj) {...}可能在Safari,Firefox中有所不同

该函数返回一个对象,该对象具有按字母顺序插入的排序键:

function orderKeys(obj, expected) {

  var keys = Object.keys(obj).sort(function keyOrder(k1, k2) {
      if (k1 < k2) return -1;
      else if (k1 > k2) return +1;
      else return 0;
  });

  var i, after = {};
  for (i = 0; i < keys.length; i++) {
    after[keys[i]] = obj[keys[i]];
    delete obj[keys[i]];
  }

  for (i = 0; i < keys.length; i++) {
    obj[keys[i]] = after[keys[i]];
  }
  return obj;
}
Run Code Online (Sandbox Code Playgroud)

这是一个快速测试:

var example = { 
      "3": "charlie",
      "p:style": "c",
      "berries": "e",
      "p:nvSpPr": "a",
      "p:txBody": "d",
      "apples": "e",
      "5": "eagle",
      "p:spPr": "b"
    }

var obj = orderKeys(example);
Run Code Online (Sandbox Code Playgroud)

这回来了

{ '3': 'charlie',
  '5': 'eagle',
  apples: 'e',
  berries: 'e',
  'p:nvSpPr': 'a',
  'p:spPr': 'b',
  'p:style': 'c',
  'p:txBody': 'd' }
Run Code Online (Sandbox Code Playgroud)

然后,您可以获得订购的密钥:

Object.keys(obj) 
Run Code Online (Sandbox Code Playgroud)

哪个回报

["3", "5", "apples", "berries", "p:nvSpPr", "p:spPr", "p:style", "p:txBody"]
Run Code Online (Sandbox Code Playgroud)

  • @VaelVictus 很好,它是从单元测试中复制粘贴的,现在不需要了。 (2认同)

mac*_*mac 12

这是一个很好的功能解决方案:

基本上,

  1. 将密钥提取到列表中 Object.keys
  2. sort 按键
  3. 将列表缩减回对象以获得所需结果

ES5解决方案:

not_sorted = {b: false, a: true};

sorted = Object.keys(not_sorted)
    .sort()
    .reduce(function (acc, key) { 
        acc[key] = not_sorted[key];
        return acc;
    }, {});

console.log(sorted) //{a: true, b: false}
Run Code Online (Sandbox Code Playgroud)

ES6解决方案:

not_sorted = {b: false, a: true}

sorted = Object.keys(not_sorted)
    .sort()
    .reduce((acc, key) => ({
        ...acc, [key]: not_sorted[key]
    }), {})

console.log(sorted) //{a: true, b: false}
Run Code Online (Sandbox Code Playgroud)


Cor*_*eyL 6

我会将此作为评论添加到@prototype的帖子中,但我的代表不够高。

如果有人需要@prototype 编写的orderKeys符合以下标准的版本:eslint-config-airbnb

/**
 * Returns and modifies the input object so that its keys are returned in sorted
 * order when `Object.keys(obj)` is invoked
 *
 * @param {object} obj The object to have its keys sorted
 *
 * @returns {object} The inputted object with its keys in sorted order
 */
const orderKeys = (obj) => {
  // Complying with `no-param-reassign`, and JavaScript seems to assign by reference here
  const newObj = obj;
  // Default `.sort()` chained method seems to work for me
  const keys = Object.keys(newObj).sort();

  const after = {};
  // Add keys to `after` in sorted order of `obj`'s keys
  keys.forEach((key) => {
    after[key] = newObj[key];
    delete newObj[key];
  });

  // Add keys back to `obj` in sorted order
  keys.forEach((key) => {
    newObj[key] = after[key];
  });

  return newObj;
};
Run Code Online (Sandbox Code Playgroud)

使用@prototype的测试:

const example = { 
  3: 'charlie',
  'p:style': 'c',
  berries: 'e',
  'p:nvSpPr': 'a',
  'p:txBody': 'd',
  apples: 'e',
  5: 'eagle',
  p:spPr: 'b'
}

const obj = orderKeys(example);

console.log(obj);

console.log(Object.keys(obj));
Run Code Online (Sandbox Code Playgroud)

输出以下内容:

Babel Compiler v6.4.4
Copyright (c) 2014-2015 Sebastian McKenzie

{ 3: 'charlie',
  5: 'eagle',
  apples: 'e',
  berries: 'e',
  'p:nvSpPr': 'a',
  'p:spPr': 'b',
  'p:style': 'c',
  'p:txBody': 'd' }
[ '3',
  '5',
  'apples',
  'berries',
  'p:nvSpPr',
  'p:spPr',
  'p:style',
  'p:txBody' ]
Run Code Online (Sandbox Code Playgroud)

不管它的价值如何,我在我的 React 应用程序中需要它,以便我可以对基于对象的下拉列表的选项进行排序state,该对象是在我的 API 响应后分配的。

最初我是这样做的

return (
  // ...
  <Select
    options={Object.keys(obj).sort()}
    // ...
  />
  // ...
);
Run Code Online (Sandbox Code Playgroud)

但意识到该.sort()方法将在每次重新渲染时调用,因此需要@prototypeorderKeys.

/sf/users/45200081/


And*_*Los 5

您也可以通过这种方式对其进行排序。

const data = {
  States: ['NSW', 'VIC'],
  Countries: ['GBR', 'AUS'],
  Capitals: ['SYD', 'MEL']
}

const sortedObject = Object.fromEntries(Object.entries(data).sort())
Run Code Online (Sandbox Code Playgroud)

我无法详细解释它为什么有效,但显然它工作得很好:) 如果您不相信我,请尝试自己:D

请注意,您的浏览器或 Node.js 版本应支持 Object.fromEntries

对于浏览器兼容性检查此页面底部

对于 Node,它适用于 12 及更高版本。对于来自 v1.1 的 Deno。