简体   繁体   English

使用ramda group by属性和sum指定属性的结果

[英]using ramda group by property and sum results on specified property

I need help transforming an array of objects using ramda; 我需要帮助使用ramda转换对象数组; I'd like to 我想

  1. group by a specified property 按指定属性分组
  2. sum another property on the resulting set 在结果集上加上另一个属性

given an array like this: 给出这样的数组:

var arr = [
  {
    title: "scotty",
    age: 22,
    score: 54,
    hobby: "debugging"

  },  {
    title: "scotty",
    age: 22,
    score: 19,
    hobby: "debugging"
  }
  ,  {
    title: "gabriel",
    age: 40,
    score: 1000
  }
];

if I want to group by title and sum on age it should return the following summary of values 如果我想按title分组并按age ,则应返回以下值的摘要

var arr = [
  {
    title: "scotty",
    age: 44,
    hobby: "debugging",
  }
  ,  {
    title: "gabriel",
    age: 40,
    score: 1000
  }
];

when the unspecified property's differ in value they should be omitted, but if unspecified property's are the same in value it should remain in the final result. 当未指定的属性值不同时,应省略它们,但如果未指定的属性值相同,则应保留在最终结果中。

** My Solution ** **我的解决方案**

    /*
 * [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);

To fix your groupBy problem you need to see that groupBy takes a key-generation function function and not a binary predicate. 要修复groupBy问题,您需要看到groupBy采用密钥生成函数函数而不是二元谓词。

So, for instance, 所以,例如,

const byTitle = R.groupBy(R.prop('title'));

This should get you through your current block. 这应该可以帮助您完成当前的阻止。 If you need help with the summation, let me know. 如果您需要求助的帮助,请告诉我。

Update : 更新

You asked for my approach. 你问我的方法。 It does differ from yours a fair bit. 它与你的确有所不同。 I would probably do something like this: 我可能会这样做:

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)

Or if I wanted it a little more concise, I might switch to: 或者,如果我想要它更简洁,我可能会切换到:

const sumBy = prop => lift(
  reduce((current, val) => evolve({[prop]: add(val[prop])}, current)
))(head, tail)

Note that sumBy is relatively reusable. 请注意, sumBy是相对可重用的。 It's not perfect, because it would fail on an empty list. 它并不完美,因为它会在空列表中失败。 But in our case, we know that the output of groupBy will never create such an empty list for a key. 但在我们的例子中,我们知道groupBy的输出永远不会为密钥创建这样的空列表。 And any version which didn't fail on an empty list would need a way to supply the default case. 任何在空列表中没有失败的版本都需要一种方法来提供默认情况。 It simply gets ugly. 它简直变得丑陋。

You can see this in action on the Ramda REPL . 你可以在Ramda REPL上看到这个。

You could probably make a more easily readable version of groupSumBy using pipe or compose if you were willing to call first with the groupOn and sumOn values, then call the resulting function with the values, that is, if the invocation looked like this: 如果您愿意首先使用groupOnsumOn值调用,则groupSumBy使用pipecompose创建更容易阅读的groupSumBy版本, groupSumBy使用值调用结果函数,即,如果调用如下所示:

groupSumBy('title', 'age')(people)
// or more likely:
const foo = groupSumBy('title', age)
foo(people)

But I leave that as an exercise for the reader. 但我把它作为读者的练习。

using ramda group by property and sum results on specified property 使用ramda group by属性和sum指定属性的结果

One option is to reduceBy as follows: 一种选择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));

The output has grouped by title and has summed the age . 输出按title分组,并将age相加。

{                  
  "scotty": 44,    
  "gabriel": 40    
}                  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM