使用 ramda group by 属性 并对指定的 属性 的结果求和
using ramda group by property and sum results on specified property
我需要帮助使用 ramda 转换对象数组;我想
- 按指定分组 属性
- 求和另一个 属性
结果集
给定一个这样的数组:
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
如果我想按 title
分组并在 age
上求和,它应该 return 以下值摘要
var arr = [
{
title: "scotty",
age: 44,
hobby: "debugging",
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
当未指定的属性的值不同时,它们应该被省略,但如果未指定的属性的值相同,它应该保留在最终结果中。
** 我的解决方案 **
/*
* [Student]
*/
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
/*
* String -> [[Student]] -> [Student]
*/
var sumOnProperty = function(property, v){
var sum = (x,y) => x[property] + y[property];
var new_array = [];
v.forEach(arr => {
if(arr.length > 1){
arr[0]["age"] = arr.reduce(sum)
new_array.push(arr[0]);
} else {
if(arr.length != 0){
new_array.push(arr[0]);
}
}
})
return new_array;
}
/*
* String -> String -> [Student] -> [Student]
*/
var groupsumBy = function(groupproperty, sumproperty, arr){
// create grouping
var grouping = R.groupBy(R.prop(groupproperty), arr)
// convert grouping object to array
var result1 = R.valuesIn(grouping);
// sum each grouping and flatten 2d array
var result2 = sumOnProperty(sumproperty, result1);
return result2;
}
groupsumBy("title","age",arr);
using ramda group by property and sum results on specified property
一个选项is to reduceBy
如下:
import * as R from "ramda";
const arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
const reduction =
R.reduceBy((acc, next) => acc + next.age, 0, (x) => x.title, arr);
console.log(JSON.stringify(reduction, undefined, 2));
输出已按 title
分组并已对 age
求和。
{
"scotty": 44,
"gabriel": 40
}
要解决您的 groupBy
问题,您需要了解 groupBy
采用密钥生成函数而不是二元谓词。
所以,例如,
const byTitle = R.groupBy(R.prop('title'));
这应该可以帮助您完成当前的障碍。如果您在求和方面需要帮助,请告诉我。
更新:
你问我方法。它确实和你的有点不同。我可能会做这样的事情:
const sumBy = prop => vals => reduce(
(current, val) => evolve({[prop]: add(val[prop])}, current),
head(vals),
tail(vals)
)
const groupSumBy = curry((groupOn, sumOn, vals) =>
values(map(sumBy(sumOn))(groupBy(prop(groupOn), vals)))
)
groupSumBy('title', 'age', people)
或者如果我想让它更简洁一点,我可能会切换到:
const sumBy = prop => lift(
reduce((current, val) => evolve({[prop]: add(val[prop])}, current)
))(head, tail)
请注意,sumBy
相对可重用。它并不完美,因为它会在空列表上失败。但在我们的例子中,我们知道 groupBy 的输出永远不会为键创建这样一个空列表。任何没有在空列表上失败的版本都需要一种方法来提供默认情况。它只会变得丑陋。
您可以在 Ramda REPL.
上看到实际效果
如果您愿意先使用 groupOn
和 sumOn
值调用,则可以使用 pipe
or compose
制作更易于阅读的 groupSumBy
版本,然后调用具有值的结果函数,也就是说,如果调用如下所示:
groupSumBy('title', 'age')(people)
// or more likely:
const foo = groupSumBy('title', age)
foo(people)
但我将其留作 reader 的练习。
我需要帮助使用 ramda 转换对象数组;我想
- 按指定分组 属性
- 求和另一个 属性 结果集
给定一个这样的数组:
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
如果我想按 title
分组并在 age
上求和,它应该 return 以下值摘要
var arr = [
{
title: "scotty",
age: 44,
hobby: "debugging",
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
当未指定的属性的值不同时,它们应该被省略,但如果未指定的属性的值相同,它应该保留在最终结果中。
** 我的解决方案 **
/*
* [Student]
*/
var arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
/*
* String -> [[Student]] -> [Student]
*/
var sumOnProperty = function(property, v){
var sum = (x,y) => x[property] + y[property];
var new_array = [];
v.forEach(arr => {
if(arr.length > 1){
arr[0]["age"] = arr.reduce(sum)
new_array.push(arr[0]);
} else {
if(arr.length != 0){
new_array.push(arr[0]);
}
}
})
return new_array;
}
/*
* String -> String -> [Student] -> [Student]
*/
var groupsumBy = function(groupproperty, sumproperty, arr){
// create grouping
var grouping = R.groupBy(R.prop(groupproperty), arr)
// convert grouping object to array
var result1 = R.valuesIn(grouping);
// sum each grouping and flatten 2d array
var result2 = sumOnProperty(sumproperty, result1);
return result2;
}
groupsumBy("title","age",arr);
using ramda group by property and sum results on specified property
一个选项is to reduceBy
如下:
import * as R from "ramda";
const arr = [
{
title: "scotty",
age: 22,
score: 54,
hobby: "debugging"
}, {
title: "scotty",
age: 22,
score: 19,
hobby: "debugging"
}
, {
title: "gabriel",
age: 40,
score: 1000
}
];
const reduction =
R.reduceBy((acc, next) => acc + next.age, 0, (x) => x.title, arr);
console.log(JSON.stringify(reduction, undefined, 2));
输出已按 title
分组并已对 age
求和。
{
"scotty": 44,
"gabriel": 40
}
要解决您的 groupBy
问题,您需要了解 groupBy
采用密钥生成函数而不是二元谓词。
所以,例如,
const byTitle = R.groupBy(R.prop('title'));
这应该可以帮助您完成当前的障碍。如果您在求和方面需要帮助,请告诉我。
更新:
你问我方法。它确实和你的有点不同。我可能会做这样的事情:
const sumBy = prop => vals => reduce(
(current, val) => evolve({[prop]: add(val[prop])}, current),
head(vals),
tail(vals)
)
const groupSumBy = curry((groupOn, sumOn, vals) =>
values(map(sumBy(sumOn))(groupBy(prop(groupOn), vals)))
)
groupSumBy('title', 'age', people)
或者如果我想让它更简洁一点,我可能会切换到:
const sumBy = prop => lift(
reduce((current, val) => evolve({[prop]: add(val[prop])}, current)
))(head, tail)
请注意,sumBy
相对可重用。它并不完美,因为它会在空列表上失败。但在我们的例子中,我们知道 groupBy 的输出永远不会为键创建这样一个空列表。任何没有在空列表上失败的版本都需要一种方法来提供默认情况。它只会变得丑陋。
您可以在 Ramda REPL.
上看到实际效果如果您愿意先使用 groupOn
和 sumOn
值调用,则可以使用 pipe
or compose
制作更易于阅读的 groupSumBy
版本,然后调用具有值的结果函数,也就是说,如果调用如下所示:
groupSumBy('title', 'age')(people)
// or more likely:
const foo = groupSumBy('title', age)
foo(people)
但我将其留作 reader 的练习。