【问题标题】:Sort array of objects into Top N using lodash with n+1 as "others"使用 lodash 将对象数组排序到 Top N 中,n+1 为“其他”
【发布时间】:2015-08-17 20:39:17
【问题描述】:

假设我有这个数据结构,示例输入:

[ {name: "a", val:1},
  {name: "b", val:2},
  {name: "c", val:3},
  {name: "d", val:4},
  {name: "e", val:5},
  {name: "f", val:1},
  {name: "g", val:2},
  {name: "h", val:1},
]

我想输出 2 个数组:

第一个是来自对象的 val 属性,首先是顶部(最高)值,然后是其余元素的总和。如果我们假设 n=5,作为前 5 个结果+“其余”。因此,array[5] 上的这个数组 = 不在前 5 名中的所有 val 属性的总和。示例输出:

[2,3,4,5,2,3]

第二个数组是前 5 个对应的 name 属性,array[5] = "others",或者其他任意字符串。示例输出:

["b","c","d","e","g","others"]

如何使用 lodash 以最大的效率和/或最大的代码清晰度来实现这一点? lodash

编辑:示例代码:

       var n = 5;
  var input = [ 
      {name: "a", val:1},
      {name: "b", val:2},
      {name: "c", val:3},
      {name: "d", val:4},
      {name: "e", val:5},
      {name: "f", val:1},
      {name: "g", val:2},
      {name: "h", val:1},
    ];
    var sortedArray = _.sortByOrder(input, ['val'], [false]);
    var topNValues = _.pluck(_.slice(sortedArray, 0, n), 'val');
    var restValues = _.pluck(_.slice(sortedArray, n, sortedArray.length), 'val');
    var restAdded = _.reduce(restValues, function(i, j) {
    return i + j;
}, 0); 
    topNValues.splice(n, 0,restAdded);
    $scope.array1 = topNValues; 
    var names = _.pluck(_.slice(sortedArray, 0, n), 'name');
    names.splice(n,0,"others");
    $scope.array2 = names;

一定有比我的 jsfiddle 更干净、更链式的方式:http://jsfiddle.net/u1w4da6r/2/

【问题讨论】:

  • 我建议先去获得最大的清晰度。 Afaik,lodash 没有top k algorithm,自己实现一个可能很复杂。
  • 请将您已有的代码放入您的问题中,而不仅仅是放在小提琴中(作为附加帮助器很好)

标签: javascript arrays json angularjs lodash


【解决方案1】:

所以它不是一个单一的链,但它似乎很容易阅读。我没有做过任何性能测试,但易于理解应该是您的主要目标。

Codepen

function groupOthers (obj, n) {
  var indicesToKeep = _.chain(obj)
    .map(function (item, index) { //zip each item with its index
      return {item: item, index: index}
    })
    .sortBy(function (zipped) { //sort by the val (highest to lowest)
      return -zipped.item.val
    })
    .take(n) //take the top 5
    .map('index') // we only care about the indices
    .value()

  var partitioned = _.partition(obj, function (item, index) {
    return _.includes(indicesToKeep, index)
  })

  var finalObjJoined = partitioned[0].concat({
    name: 'others',
    val: _.sum(partitioned[1], 'val')
  })

  return [_.map(finalObjJoined, 'name'), _.map(finalObjJoined, 'val')]
}

console.log(groupOthers(x, 5))

【讨论】:

  • 请注意,这适用于最新版本的 Lodash。由于我不想调查的原因,Lodash 3.5 似乎失败了:)
猜你喜欢
  • 2013-06-11
  • 1970-01-01
  • 2013-11-27
  • 2017-08-20
  • 1970-01-01
  • 1970-01-01
  • 2022-07-11
  • 2021-10-08
  • 2017-01-01
相关资源
最近更新 更多