【问题标题】:Trying to sort {key: object} pairs by object property with Javascript and Underscore尝试使用 Javascript 和下划线按对象属性对 {key: object} 对进行排序
【发布时间】:2013-12-31 15:09:54
【问题描述】:
{
  "TR":{
    "total_fans":1848,
    "country_name":"Turkey"
  },
  "US":{
    "total_fans":1097,
    "country_name":"United States"
  },
  "DE":{
    "total_fans":915,
    "country_name":"Germany"
  },
  "MX":{
    "total_fans":1148,
    "country_name":"Mexico"
  },
  "RS":{
    "total_fans":359,
    "country_name":"Serbia"
  },
  "IT":{
    "total_fans":798,
    "country_name":"Italy"
  }
}

我想根据粉丝对此进行排序。例如,在这种情况下,它应该是“TR”、“MX”、“US”……等等,如果有帮助的话,使用 JS 和下划线。 谢谢!

【问题讨论】:

  • 对象的语法错误...是整个对象吗?
  • 我编辑了它,我想我搞砸了,但看起来 Doorknob 修复了它。有没有办法在stackoverflow中格式化它而不仅仅是间距?

标签: javascript sorting object underscore.js


【解决方案1】:

JavaScript 对象是无序的,因此您将无法排序或以其他方式定义特定顺序。

您可以将属性转换为数组,然后对其进行排序,但这与您将得到的差不多。

由于您似乎想按粉丝数量排序,您可以这样做。

Object.keys(myObject)
    .sort(function(a,b) {
        return myObject[a].total_fans - myObject[b].total_fans;
    }).forEach(function(key) {
        console.log(myObject[key]);
    });

要支持 IE8 及更低版本,您需要为 Object.keysArray.prototype.forEach 安装补丁。

正如 Bruce Lim 所说,这是一种升序排序。要下降,请在 return 之后交换 - 运算符的操作数。

return myObject[b].total_fans - myObject[a].total_fans;

【讨论】:

  • 他其实是想按粉丝排序的。
  • @natecraft1 将属性更改为 total_fans 顺便说一句。它可以对 ASC 进行排序。对 DSC 进行排序:返回 myObject[b].total_fans - myObject[a].total_fans;
  • +1 哇,干得好饼干怪物!我完全忘记了Object.keys...这正是我试图用Object.ownProps 做的事情,但更标准。你的答案显然是最好的。
  • @EthanBrown:谢谢! :-)
  • 哟饼干,好东西。你会给这个问题起什么名字,这样大多数有同样问题的人都会遇到这个问题?我还在学习行话;)
【解决方案2】:

如果您不关心 IE obj 中:

var sorted = Object
   .keys(obj)
   .map(function(key) {
       // Put the country in the item?
       obj[key].country = key;
       return obj[key];
   })
   .sort(function(a, b) {
       if (a.total_fans > b.total_fans) {
           return -1;
       } else if (b.total_fans > a.total_fans) {
           return 1;
       }
       return 0;
   });

这将为您提供一个Array,按照粉丝最多的项目排在第一位,并在您需要时将国家/地区代码添加到每个项目中(如果不需要,请省略)。

【讨论】:

  • jacob 谢谢这是一个很棒的答案,我从中学到了很多
【解决方案3】:

尝试用数组排序:

var array = [];

// copy object to array
for (var x in yourObject) array.push([x, yourObject[x].total_fans]);

// sort array
array.sort(function(item1, item2) { return item1[1] - item2[1] });

// now get the keys
var keys = [];
for (var i = 0; i < array.length; i ++) keys.push(array[i][0]);

// keys = ["RS", "IT", "DE", "US", "MX", "TR"]

请注意,如果您不关心旧的 IE,使用 map 获取密钥的步骤可能会更容易。

【讨论】:

    【解决方案4】:

    更新:多亏了与 Doorknob 的热烈但有益的交流,我意识到他在修改 Object.prototype 时要小心谨慎,这是一个很好的观点。我修改了答案,通过使新方法不可枚举,使 Object.prototype 的扩展不那么具有侵入性。谢谢,门把手!

    更新 2:我现在意识到 OP 明智地选择正确答案是正确的。 Object.keys 完全符合我的 ownProps 方法(见下文)所做的,而且它是一个标准(尽管您仍然需要在 IE8 中进行 polyfill)。我会删除这个答案,因为 cookie monster 确定了它,但我认为这是一个有用的讨论,即使 ownPropsObject.keys 是多余的,它可能会教给某人......一些东西。

    我编写了一个名为ownProps 的便捷函数,它返回对象的所有属性名称(不包括原型链中的属性)。这是一种更实用的方式来执行 Doorknob 上面的建议:

    // retrieves all of the properties of an object as an array, 
    // omitting properties in the prototype chain; note that we use
    // Object.defineProperty so we can make this non-enumerable, thereby
    // making a safer modification of Object.prototype
    Object.defineProperty(Object.prototype,'ownProps',{
      enumerable: false,
      value: function() {
        var props = []; for( var prop in this ) { 
            if( this.hasOwnProperty( prop ) ) props.push( prop ); 
        } 
        return props;
      }
    });
    

    有了这个,您可以使用自定义排序功能对您的对象进行排序:

    var obj = {"TR":{"fans":1848,"country_name":"Turkey"}/*...*/}
    
    var sortedKeys = obj.ownProps().sort(function(a,b){
        return obj[a].fans - obj[b].fans;
    });
    

    【讨论】:

    • 不同意,门把手。 JavaScript 的优点之一。并非道格拉斯·克罗克福德所说的一切都是镀金的。
    • 好吧,假设有人去做if (someVariable.ownProps === undefined) someVariable.ownProps = ['some', 'stuff']。哎呀,你的代码刚刚打破了:(
    • 相对于...你还做什么?如果我在Object.prototype 上创建了一个自定义函数会怎样?有人可能会出现并覆盖它。
    • 在 JavaScript 中,有一百万个机会把事情搞砸……这是野兽本性的一部分。虽然我不会因为你放下的好理由而随意修改Object.prototype,但一些适当且合理的扩展并不是世界末日。
    • FWIW,“并不是道格拉斯·克罗克福德所说的一切都是镀金的。” 是我完全同意的声明! ;-D
    【解决方案5】:

    解决方案:http://jsfiddle.net/az7XN/

    假设你的粉丝对象是fansObj

    for(prop in fansObj){
       console.log(prop, fansObj[prop]);
    }
    

    输出示例:TR, {"fans":1848,"country_name":"Turkey" }

    for circle 之前声明数组变量并将每个 obj 推到那里:

    var arr = [];
    for(prop in fansObj){
       console.log(prop, fansObj[prop]);
       arr.push(fansObj[prop]);
    }
    

    然后排序:

    arr.sort(function(a,b){parseInt(b['total_fans'],10) - parseInt(a['total_fans'])});
    

    parseInt(obj,10) 将接受将对象从十进制转换为整数。

    现在您已经对数组进行了排序(取决于排序函数内部的比较(a-b=desc 或 b-a=asc))。

    用到的功能:

    for..in

    Array.prototype.sort()

    parseInt()

    【讨论】:

    • 更新:添加排序。首先我写了如何在对象中抛出所有属性,然后添加排序。
    • 不需要parseInt...total_fans 属性已经是一个数字了。
    • @EthanBrown 是的,你是对的,但我认为这是 JSON 中的字符串,所以我添加了解析。拥有整数解析器会更好,因为在 javascript 中您可以将任何内容设置为 total_fans
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 2010-11-24
    • 1970-01-01
    • 2016-04-23
    相关资源
    最近更新 更多