【问题标题】:How can I order the items in an Object?如何订购对象中的项目?
【发布时间】:2015-07-19 20:35:18
【问题描述】:

我想用 node.js 计算字符串的出现次数,并开始实现一个字典,如下所示:

var dict = {}

// Example content ("string" = count)
dict["alpha"] = 12
dict["beta"] = 39

// Increment count (working)
dict["alpha"]++

但是我如何从最高计数到最低计数对这本字典进行排序?是否有任何内置排序或我必须自己实现它?

我想列出文件中从最高到最低计数的输出,每一行是:

<count> <string>

【问题讨论】:

  • 您不能创建 Ordered 对象。预期的结果是什么?
  • 我想列出文件中从最高到最低计数的输出,每一行:
  • 对象是无序的!使用数组进行排序!
  • 您必须将对象转换为数组,对数组进行排序,然后从排序后的数组中重新定义对象属性,如果键不是数字,则将保留插入顺序,这与流行的观点和技术规范不明确。如果有人可以展示一个没有被保留的非数字属性顺序的片段,我很乐意看到它。
  • ejohn.org/blog/javascript-in-chrome(用于循环顺序)

标签: javascript node.js sorting object


【解决方案1】:

对象是无序的,因为键是基于散列值存储的。所以,没有所谓的排序对象。

但是,您可以简单地根据count 对键进行排序,然后直接在其上应用forEach,就像这样

> Object.keys(dict).sort(function(key1, key2) {
...     return dict[key2] - dict[key1];
... }).forEach(function(currentKey) {
...     console.log(currentKey, dict[currentKey]);
... });
beta 39
alpha 12

要理解这一点,您可以逐步将对象转换为对数组,如下所示

> var dict = {}
undefined
> dict["alpha"] = 12
12
> dict["beta"] = 39
39
> var temp = Object.keys(dict).map(function(currentKey) {
...     return [currentKey, dict[currentKey]];
... });
undefined
> temp
[ [ 'alpha', 12 ],
  [ 'beta', 39 ] ]

然后根据第二个元素对它们进行排序,用Array.prototype.sort,像这样

> temp.sort(function(pair1, pair2) {
...     return pair2[1] - pair1[1];
... });
[ [ 'beta', 39 ],
  [ 'alpha', 12 ] ]

然后按你喜欢的方式打印出来,像这样

> temp.forEach(function(currentPair) {
...     console.log(currentPair[0], currentPair[1]);
... })
beta 39
alpha 12

既然要把结果写到文件里,可以这样写

> var fileWriter = require("fs").createWriteStream('Output.txt');
undefined
> Object.keys(dict).sort(function (key1, key2) {
...     return dict[key2] - dict[key1];
... }).forEach(function (currentKey) {
...     fileWriter.write(currentKey + " " + dict[currentKey] + "\n");
... });
undefined
> fileWriter.end();
undefined
> require("fs").readFileSync("Output.txt").toString()
'beta 39\nalpha 12\n'

您可能需要查看this amazing answer,以更好地了解 JavaScript 中的排序方式。

【讨论】:

  • 您能证明您的论点,即未保留对象属性顺序吗?尽管尝试了许多浏览器和 node.js,但我似乎无法重现您描述的行为......有什么想法吗?
  • @dandavis 我不确定我是否正确理解了您的问题。
  • @dandavis 试试Object.keys({"2": 1, "1": 1});
  • @dandavis:最初的 ECMAScript 规范一直到 ES5 都明确指定没有对象属性顺序——也就是说,你永远不能期望它有任何有意义的顺序。就你所知,它可以是随机的。然而,所有现代浏览器都实现了相同的键顺序——首先是整数,然后是插入顺序(最后一个没有这样做的浏览器是 Chrome,但他们大约在一年前“修复”了它)。程序员无意中发现了浏览器实现中的这种相似性,并且编写了依赖于它的代码。所以现在,ES6 明确指定对象属性顺序。
  • @dandavis:在我看来,ES6 规范做错了事——鼓励错误代码而不是阻止它。在我自己的代码中,我仍然将对象键顺序视为“随机”。依赖于实现细节而不是语言特性的代码是有缺陷的。
【解决方案2】:

继续 Rob 的回答,您可以在排序后的对象数组中获取具有如下值的项目:

var res = Object.keys(dict).map(function(key ) {
  return { key: key, value : dict[key] };
}).sort(function(a, b) { 
   return b.value - a.value
});

其中 res 是 [{key:"alpha",value:16},...] 形式的排序数组

然后可以使用 reduce 将其转换为字符串

var strToFile = res.reduce( function(p,n) { 
 return p + n.value+" "+n.key+"\n"; },"");

结果看起来像

39 beta
12 alpha

【讨论】:

    【解决方案3】:

    您可以获得最常出现的单词的数组(尽管数组中没有值);

    Object.keys(dict).sort(function(a, b) { 
       return dict[b]-dict[a]; 
    });
    // ["beta", "alpha"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-28
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多