按值排序地图/哈希,保留键

时间:2016-03-18 08:16:38

标签: javascript underscore.js lodash immutable.js

我有一段时间找到这个答案。

我想在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;
});

但我不相信这存在。 这要问太多了吗?我怎样才能找到这个功能?

2 个答案:

答案 0 :(得分:3)

  

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

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

使用该信息,如果您的密钥都是不符合整数索引的字符串,那么在符合ES2015的引擎上,我们可以这样做:

  1. 以任何顺序开始使用属性(例如acb

  2. 使用Object.keys将这些密钥作为数组

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

  4. 按值排序数组

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

  6. 最终结果是一个对象,其属性按创建顺序排列,这是它们的值的顺序,因为我们按顺序创建它们。我们可以通过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 => {
      snippet.log("hash['" + n + "'] = " + hash[n]);
    });
    <!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
    <script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

    除此之外,正如我在对这个问题的评论中所说,我不确定你为什么要这样做。看起来如果我们知道你的最终目标是什么,我们可能会指出你一个更有用的方向......

答案 1 :(得分:3)

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>