使用ramda转换集合

时间:2017-11-03 21:25:23

标签: javascript functional-programming ramda.js

我想使用ramba进行以下转换

输入集合

const vals = [
        {metric: "Sales", measure:100, period_end_date: "2021-12-31", period_type: 'Annual' },
        {metric: "EBT", measure:101,  period_end_date: "2021-12-31", period_type: 'Annual' },
        {metric: "Sales", measure:100, period_end_date: "2021-09-30", period_type: 'Qtr' },
        {metric: "EBT", measure:101,  period_end_date: "2021-09-30", period_type: 'Qtr' }
       ]

输出

 {  
   "2021-09-30|Qtr": [{"Sales": 100}, {"EBT": 101],  
   "2021-12-31|Annual": [{"Sales": 100, }, {"EBT": 101,}] 
 }

我能够非常接近这个

const keyGen = compose(objOf('key'), join('|'),  props(['period_end_date','period_type']))// + '|' + prop("period_type",o) }

const valGen = compose(apply(objOf), R.ap([R.prop('metric'), R.prop('measure')]), of )

const f4 = map(compose(apply(merge), R.ap([keyGen, valGen]), of))

const result =compose(groupBy(prop('key')),f4 ) (vals)

这给了我以下结果

{"2021-09-30|Qtr": [{"Sales": 100, "key": "2021-09-30|Qtr"}, 
                    {"EBT": 101, "key": "2021-09-30|Qtr"}], 
 "2021-12-31|Annual": [{"Sales": 100, "key": "2021-12-31|Annual"}, 
                       {"EBT": 101, "key": "2021-12-31|Annual"}]}

现在我需要从内部集合中删除key。我想知道是否有更好的选择。

3 个答案:

答案 0 :(得分:1)

也许您应该简化代码并使用一个简单的函数将集合减少到所需的输出?我使用了Array.prototype.reduce,它很容易翻译成Ramda的功能性,无点,咖喱风格:

const convert = (acc, item) => {
  const name = `${item.period_end_date}|${item.period_type}`
  if (!acc[name]) acc[name] = []
  acc[name].push({ [item.metric]: item.measure })
  return acc
}

const transform = R.reduce(convert, {})
transform(vals)

没有Ramda的工作片段:

const vals = [{
    metric: "Sales",
    measure: 100,
    period_end_date: "2021-12-31",
    period_type: 'Annual'
  },
  {
    metric: "EBT",
    measure: 101,
    period_end_date: "2021-12-31",
    period_type: 'Annual'
  },
  {
    metric: "Sales",
    measure: 100,
    period_end_date: "2021-09-30",
    period_type: 'Qtr'
  },
  {
    metric: "EBT",
    measure: 101,
    period_end_date: "2021-09-30",
    period_type: 'Qtr'
  }
]

const result = vals.reduce((acc, item) => {
  const name = `${item.period_end_date}|${item.period_type}`
  if (!acc[name]) acc[name] = []
  acc[name].push({
    [item.metric]: item.measure
  })
  return acc
}, {})

console.log(result)

答案 1 :(得分:0)

R.reduceBy可用于对列表中的项目进行分组,然后减少具有相同密钥的每组项目。



const vals = [
  {metric: "Sales", measure:100, period_end_date: "2021-12-31", period_type: 'Annual' },
  {metric: "EBT", measure:101,  period_end_date: "2021-12-31", period_type: 'Annual' },
  {metric: "Sales", measure:100, period_end_date: "2021-09-30", period_type: 'Qtr' },
  {metric: "EBT", measure:101,  period_end_date: "2021-09-30", period_type: 'Qtr' }
]

const fn = R.reduceBy(
  (list, {metric, measure}) => R.append({[metric]: measure}, list),
  [],
  ({period_end_date, period_type}) => `${period_end_date}|${period_type}`,
)

console.log(fn(vals))

<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

另一种可能性是这样的:

&#13;
&#13;
const vals = [
  {metric: "Sales", measure:100, period_end_date: "2021-12-31", period_type: 'Annual' },
  {metric: "EBT", measure:101,  period_end_date: "2021-12-31", period_type: 'Annual' },
  {metric: "Sales", measure:100, period_end_date: "2021-09-30", period_type: 'Qtr' },
  {metric: "EBT", measure:101,  period_end_date: "2021-09-30", period_type: 'Qtr' }
]

const fn = R.pipe(
  R.groupBy(({period_end_date, period_type}) => `${period_end_date}|${period_type}`),
  R.map(R.map(R.lift(R.objOf)(R.prop('metric'), R.prop('measure'))))
);

console.log(fn(vals))
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
&#13;
&#13;
&#13;

此处的关键点是lift objOf,因此它不会处理,而是适用于值的容器,在此case,返回它们的函数(prop('metric')prop('measure')。)