簡體   English   中英

有沒有辦法對 JavaScript 對象中的鍵進行排序/排序?

[英]Is there a way to sort/order keys in JavaScript objects?

例如以下

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

印刷

States
Countries
Capitals

有沒有辦法按字母順序排序以便打印

Capitals
Countries
States

不在對象本身內:對象的屬性集合是無序的。

您可以做的一件事是使用Object.keys() ,並對數組進行排序,然后對其進行迭代。

Object.keys(data)
      .sort()
      .forEach(function(v, i) {
          console.log(v, data[v]);
       });

不支持 ECMAScript 第 5 版的瀏覽器的補丁(實現):

這是一個很好的功能解決方案:

基本上,

  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}

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}

就在這里。 不在 ECMAScript 標准內,但跨瀏覽器和 Node.js 支持,並且顯然穩定。 請參閱https://stackoverflow.com/a/23202095/645715

編輯:這將返回一個對象,其中鍵是有序的。 您可以使用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;
}

這是一個快速測試:

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

這返回

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

然后,您可以按以下方式獲取有序鍵:

Object.keys(obj) 

哪個返回

["3", "5", "apples", "berries", "p:nvSpPr", "p:spPr", "p:style", "p:txBody"]

您也可以通過這種方式對其進行排序。

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

const sortedObject = Object.fromEntries(Object.entries(data).sort())

我無法詳細解釋為什么它有效,但顯然它完美無缺:) 如果您不相信我,請嘗試自己:D

請注意,您的瀏覽器或 Node.js 版本應支持Object.fromEntries

有關瀏覽器兼容性,請查看本頁底部

對於 Node,它將適用於 12 及更高版本。 對於 v1 中的 Deno。

我會將此作為評論添加到@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;
};

使用@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));

輸出以下內容:

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' ]

不管它值多少錢,我都需要在我的 React 應用程序中使用它,以便我可以對基於state對象的下拉列表的選項進行排序,該狀態對象是在我的 API 響應后分配的。

最初我做了

return (
  // ...
  <Select
    options={Object.keys(obj).sort()}
    // ...
  />
  // ...
);

但是意識到.sort()方法會在每次重新渲染時被調用,因此需要@prototypeorderKeys實現。

https://stackoverflow.com/users/645715/prototype

這是使用lodash對對象的鍵進行排序的單線器

_.chain(obj).toPairs().sortBy(0).fromPairs().value()

使用您的示例數據:

var data = {
    'States': ['NSW', 'VIC'],
    'Countries': ['GBR', 'AUS'],
    'Capitals': ['SYD', 'MEL']
}
data = _.chain(data)
  .toPairs() // turn the object into an array of [key, value] pairs
  .sortBy(0) // sort these pairs by index [0] which is [key]
  .fromPairs() // convert array of pairs back into an object {key: value}
  .value() // return value
/*
{
  Capitals: [ 'SYD', 'MEL' ],
  Countries: [ 'GBR', 'AUS' ],
  States: [ 'NSW', 'VIC' ]
}
*/

如果您有一個更復雜的對象,其中一些屬性也是對象,這是一個很好的解決方案。

const sortObject = (obj: any) => {
  const sorted = Object.keys(obj)
    .sort()
    .reduce((accumulator, key) => {
      if (typeof obj[key] === "object") {
        // recurse nested properties that are also objects
        if (obj[key] == null) {
          accumulator[key] = null;
        } else if (isArray(obj[key])) {
          accumulator[key] = obj[key].map((item: any) => {
            if (typeof item === "object") {
              return sortObject(item);
            } else {
              return item;
            }
          });
        } else {
          accumulator[key] = sortObject(obj[key]);
        }
      } else {
        accumulator[key] = obj[key];
      }
      return accumulator;
    }, {});
  return sorted;
};

如果轉換為數組不適合您的模板並且您知道對象的鍵,您也可以執行以下操作:

在您的控制器中,以正確的順序定義一個帶有鍵的數組:

this.displayOrder = [
    'firstKey',
    'secondKey',
    'thirdKey'
];

在您的模板中重復 displayOrder 的鍵,然后使用 ng-init 引用回您的對象。

<div ng-repeat="key in ctrl.displayOrder" ng-init="entry = ctrl.object[key]">
     {{ entry.detail }}
</div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM