2017-08-17 68 views
1

我需要帮助转换使用ramda的对象数组;我想使用ramda组的属性和总和结果在指定的属性

  1. 组由一个指定的属性
  2. 总和在 另一个属性所得设置

给定的阵列是这样的:

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

回答

1

要解决您的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中看到此操作。

使用pipecompose更容易阅读的版本的groupSumBy,如果你愿意与groupOnsumOn值先打电话,然后调用所产生的作用与价值,也就是说,如果调用看起来像你也许可以使这个:

​​

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

+0

我在我的问题中提出了一个解决方案,但会很高兴看到你将如何完成它 –

0

上指定属性使用ramda组由属性和求和结果

一种选择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分组,并具有su mmed age

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