按值对映射/哈希进行排序,保留键

Sort Map/Hash by values, retaining keys

本文关键字:排序 保留 哈希进 映射      更新时间:2023-09-26

我花了很多时间寻找这个问题的答案。

我想在 JavaScript 中有一个哈希,如下所示:

const hash = {
   a: 'A',
   c: 'C',
   b: 'B'
}

我想按对对象进行排序,这样它可能会变成:

const hash = {
   a: 'A',
   b: 'B',
   c: 'C',
}

现在,我意识到 POJSO 不能保证其密钥的顺序,因此我正在考虑使用immutableJS或一些对象来保证哈希中密钥的顺序。

所以我正在寻找类似的东西:

var newHash = Immutable.Map(hash).sortBy(function(key,val){
       return val;
});

但我不相信这存在。这要求是不是太过分了?如何找到此功能?

Lodash 单行:

sorted = _(hash).toPairs().sortBy(1).fromPairs().value();

现场示例:

var data = {a: 'A', c: 'C', b: 'B'};
var hash = _(data).toPairs().sortBy(1).fromPairs().value();
Object.getOwnPropertyNames(hash).forEach(n => {
  snippet.log("hash['" + n + "'] = " + hash[n]);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.6.1/lodash.min.js"></script>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

现在,我意识到 POJSO 不保证其密钥的顺序

他们现在这样做了,从ES2015开始。您仍然无法通过for-inObject.keys访问该订单,但您可以通过Object.getOwnPropertyNames 。订单由规范操作[[OwnPropertyKeys]]给出。忽略继承的属性,它基本上是:键是符合整数索引条件的字符串,按数字顺序排列;后跟作为字符串的其余键,按属性的创建顺序排列;后跟Symbol s(按创建顺序)的键。

有了这些信息,如果你的键都是不符合整数索引条件的字符串,那么在符合 ES2015 的引擎上,我们可以这样做:

  1. 以任何顺序从属性开始(例如,acb

  2. 使用 Object.keys 将这些键作为数组获取

  3. 使用 Array#map 创建一个对象数组,其中包含键和值的属性(我在下面使用了kv

  4. 按值对数组进行排序

  5. 使用 Array#reduce 创建新对象,并按排序顺序向其添加属性。(有些人,包括我自己,可能会争辩说这是对reduce的轻微误用,因为累加器实际上从未改变过,但是嘿,它让我们都是l33t[这仍然是一回事吗?]并避免中间变量。嗯,因为这是一个目标?:-) )

最终结果是一个对象,其属性按创建顺序排列,这是其值的顺序,因为我们按该顺序创建了它们。我们可以通过以下方式访问该订单 Object.getOwnPropertyNames .

// The unsorted data
let data = {
  a: 'A',
  c: 'C',
  b: 'B'
};
// Create it sorted
const hash = Object.keys(data)
  .map(key => ({k: key, v: data[key]}))
  .sort((a, b) => a.v.localeCompare(b.v))
  .reduce((o, e) => {
    o[e.k] = e.v;
    return o;
  }, {});
// Display the sorted result
Object.getOwnPropertyNames(hash).forEach(n => {
  console.log("hash['" + n + "'] = " + hash[n]);
});

<小时 />

撇开所有这些不谈,正如我在对这个问题的评论中所说,我不确定你为什么要这样做。似乎如果我们知道您的最终目标是什么,我们也许能够为您指出一个更有用的方向......