javascript - 使用 ramdajs 创建前 5 个聚合

标签 javascript functional-programming ramda.js

我想转换这个输入

[
        { country: 'France', value: 100 },
        { country: 'France', value: 100 },
        { country: 'Romania', value: 500 },
        { country: 'England', value: 400 },
        { country: 'England', value: 400 },
        { country: 'Spain', value: 130 },
        { country: 'Albania', value: 4 },
        { country: 'Hungary', value: 3 }
]

进入输出

[
      { country: 'England', value: 800 },
      { country: 'Romania', value: 500 },
      { country: 'France', value: 200 },
      { country: 'Spain', value: 130 },
      { country: 'Other', value: 8 }
]

这基本上是前 4 个国家和其他国家/地区的值(value)总和

我在 ramdajs 中使用 javascript ,我只设法在 somehow cumbersome way so far 中做到了.

我正在寻找一个优雅的解决方案:是否有任何函数式程序员能够提供他们的解决方案?或者任何有帮助的 ramda 方法的想法?

最佳答案

(每一步都得到上一步的输出,最后会把所有东西放在一起。)

第 1 步:获取总和图

你可以改变这个:

[
  { country: 'France', value: 100 },
  { country: 'France', value: 100 },
  { country: 'Romania', value: 500 },
  { country: 'England', value: 400 },
  { country: 'England', value: 400 },
  { country: 'Spain', value: 130 },
  { country: 'Albania', value: 4 },
  { country: 'Hungary', value: 3 }
]

进入这个:

{
  Albania: 4,
  England: 800,
  France: 200,
  Hungary: 3,
  Romania: 500,
  Spain: 130
}

有了这个:

const reducer = reduceBy((sum, {value}) => sum + value, 0);
const reduceCountries = reducer(prop('country'));

第 2 步:将其转换回排序数组

[
  { country: "Hungary", value: 3 },
  { country: "Albania", value: 4 },
  { country: "Spain", value: 130 },
  { country: "France", value: 200 },
  { country: "Romania", value: 500 },
  { country: "England", value: 800 }
]

你可以这样做:

const countryFromPair = ([country, value]) => ({country, value});
pipe(toPairs, map(countryFromPair), sortBy(prop('value')));

第 3 步:创建两个子组,非前 4 个国家和前 4 个国家

[
  [
    { country: "Hungary", value: 3},
    { country: "Albania", value: 4}
  ],
  [
    { country: "Spain", value: 130 },
    { country: "France", value: 200 },
    { country: "Romania", value: 500 },
    { country: "England", value: 800 }
  ]
]

你可以用它做什么:

splitAt(-4)

第四步:合并第一个子组

[
  [
    { country: "Others", value: 7 }
  ],
  [
    { country: "Spain", value: 130 },
    { country: "France", value: 200 },
    { country: "Romania", value: 500 },
    { country: "England", value: 800 }
  ]
]

有了这个:

over(lensIndex(0), compose(map(countryFromPair), toPairs, reduceOthers));

第五步:展平整个数组

[
  { country: "Others", value: 7 },
  { country: "Spain", value: 130 },
  { country: "France", value: 200 },
  { country: "Romania", value: 500 },
  { country: "England", value: 800 }
]

flatten

完整的工作示例

const data = [
  { country: 'France', value: 100 },
  { country: 'France', value: 100 },
  { country: 'Romania', value: 500 },
  { country: 'England', value: 400 },
  { country: 'England', value: 400 },
  { country: 'Spain', value: 130 },
  { country: 'Albania', value: 4 },
  { country: 'Hungary', value: 3 }
];

const reducer = reduceBy((sum, {value}) => sum + value, 0);
const reduceOthers = reducer(always('Others'));
const reduceCountries = reducer(prop('country'));
const countryFromPair = ([country, value]) => ({country, value});

const top5 = pipe(
  reduceCountries,
  toPairs,
  map(countryFromPair),
  sortBy(prop('value')),
  splitAt(-4),
  over(lensIndex(0), compose(map(countryFromPair), toPairs, reduceOthers)),
  flatten
);

top5(data)

关于javascript - 使用 ramdajs 创建前 5 个聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56037651/

相关文章:

javascript - React Webpack 动态文件名

javascript - 选项卡/浏览器关闭时触发 Angularjs 事件

c# - 循环的 Lambda 表达式转换以显示列表

javascript - 在 javascript 中是否有比这更好的方法来实现函数式递归 findById?

javascript - 循环直到...与 Ramda

javascript - 在 DOM 元素之后移动选择

javascript - 读取查询变量和主体变量有什么区别?

java - 从 scala 使用 Function<A, R> java 接口(interface)的流畅方式?

javascript - 如何编写函数以便内部应用程序隐式接收外部参数?

ramda.js - 使用 Ramda compose、groupBy 和 sort 来处理对象数组