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