使用带N +1作为“其他”的破折号将对象数组排序到前N

时间:2022-07-09 21:41:40

Assuming I have this data structure, Example 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},
]

I want to output 2 arrays :

我想输出两个数组:

The first is the val attribute from the object, with the top (highest) values first and then the sum of the remaining elements. If we assume to take n=5, as being a top 5 result + "the rest". So this array on array[5] = the sum of all the val properties not in the top 5. Example output:

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

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

The second array would be the name property corresponding to the top 5, with array[5] = "others", or some other arbitrary string. Example output:

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

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

How can this be achieved with maximum efficiency and/or maximum code clarity using lodash? lodash

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

EDIT: Example code :

编辑:示例代码:

       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;

There must be a cleaner, chained way than my jsfiddle : http://jsfiddle.net/u1w4da6r/2/

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

1 个解决方案

#1


2  

So it's not a single chain, but it seems fairly easy to read. I haven't done any performance testing, but ease-of-understanding should probably be your primary goal.

它不是一个单链,但看起来很容易读懂。我还没有做过任何性能测试,但是容易理解应该是您的主要目标。

Codepen

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))

#1


2  

So it's not a single chain, but it seems fairly easy to read. I haven't done any performance testing, but ease-of-understanding should probably be your primary goal.

它不是一个单链,但看起来很容易读懂。我还没有做过任何性能测试,但是容易理解应该是您的主要目标。

Codepen

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))