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

时间:2017-08-17 15:37:58

标签: javascript typescript ramda.js

我需要帮助使用ramda转换对象数组;我想

  1. 按指定属性分组
  2. 总结另一处房产 结果集
  3. 给出这样的数组:

    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上加总,则应返回以下值摘要

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

2 个答案:

答案 0 :(得分:4)

要修复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 上看到这一点。

如果您愿意先使用groupSumBygroupOn拨打电话,则可以使用pipecompose制作更易于阅读的sumOn版本值,然后使用值调用结果函数,也就是说,如果调用如下所示:

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

但我把它作为读者的练习。

答案 1 :(得分:1)

  

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

一个选项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    
}