使用underscore.js按值对对象数组进行排序

5

我正在尝试使用underscore.js按average属性对对象数组进行降序排序,以便最大的average排在第一位,但是我无法做到。以下是我的尝试:

var jsonData = [
{
    "title": "Dear Kitten",
    "totalCount": 1689,
    "average": 241
},
{
    "title": "Weird Things All Couples Fight About",
    "totalCount": 9966,
    "average": 1424
},
{
    "title": "If Disney Princesses Were Real",
    "totalCount": 16567,
    "average": 2367
},
{
    "title": "Secret Tricks With Everyday Objects",
    "totalCount": 24884,
    "average": 3555
},
{
    "title": "The Coolest Travel Hacks",
    "totalCount": 41847,
    "average": 8369
},
{
    "title": "5 Ways You're Drinking Coffee Wrong",
    "totalCount": 55673,
    "average": 7953
},
{
    "title": "The Perfect Way To Pour A Beer",
    "totalCount": 58097,
    "average": 58097
},
{
    "title": "Fruit You're Eating Wrong",
    "totalCount": 65570,
    "average": 32785
},
{
    "title": "Your Cat Is Judging You",
    "totalCount": 78952,
    "average": 11279
},
{
    "title": "3rd Date vs 30th Date",
    "totalCount": 84394,
    "average": 14066
}
];

console.log(_.sortBy(jsonData, "average"));

jsFiddle


1
看起来一切正常。结果按“平均值”属性的值排序。 - Pointy
1
你的fiddle中没有包含下划线:http://jsfiddle.net/y7h9cu6p/1/ - Rob M.
嗯,这是我看到的:http://i.imgur.com/8m8zMK8.png(完美的啤酒方式应该出现在顶部等等...) - Shivam
2
看起来它已经被正确排序了。问题是你想要相反的顺序,最大的“average”排在第一位吗?在排序后使用.reverse(),或者提供自己的iteratee来反转它,例如function( item ) { return -item.average; } - Michael Geary
1
你没有 JSON。你有一个包含 JS 对象的 JS 数组。 - Oriol
显示剩余11条评论
1个回答

4
问题在于您希望按照average的值以降序对数组进行排序,而不是默认的升序排序。您可以通过向_.sortBy()函数提供自定义的iteratee来实现此目的:
_.sortBy( jsonData, function( item ) { return -item.average; } )

更新的代码

但我不建议那样做。更好的方法是使用本地的JavaScript [].sort() 方法,并提供一个比较函数:

jsonData.sort( function( a, b ) { return b.average - a.average; } )

如果你要排序一个非常大的数组,使用这种方法比使用 _.sortBy() 更快。查看 _.sortBy() 的源代码可以知道原因:

Better fiddle

_.sortBy = function(obj, iteratee, context) {
  iteratee = cb(iteratee, context);
  return _.pluck(_.map(obj, function(value, index, list) {
    return {
      value: value,
      index: index,
      criteria: iteratee(value, index, list)
    };
  }).sort(function(left, right) {
    var a = left.criteria;
    var b = right.criteria;
    if (a !== b) {
      if (a > b || a === void 0) return 1;
      if (a < b || b === void 0) return -1;
    }
    return left.index - right.index;
  }), 'value');
};

除了 .sort() 方法外,它还做了很多工作——而这段代码仅仅是冰山一角,它调用的辅助函数(例如 cb())也会做很多事情。
为什么要这样做呢?直接调用 .sort() 不就行了吗?
此外,要仔细阅读那个冗长的 .sortBy() 源代码才能确定它进行的是数字排序而不是词典排序——而且文档中并没有说明
词典排序(又称字母表排序)是指将值按字符串排序,而不是按数字排序。例如,它将使用以下顺序:
[ 1424, 2367, 241, ... ]

当你自己调用原生数组.sort()方法时,你可以很容易地验证它使用数字排序:值b.average - a.average始终是一个数字。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接