使用 ramdajs 创建前 5 名聚合

Pie*_*ean 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 }
]
Run Code Online (Sandbox Code Playgroud)

进入输出

[
      { country: 'England', value: 800 },
      { country: 'Romania', value: 500 },
      { country: 'France', value: 200 },
      { country: 'Spain', value: 130 },
      { country: 'Other', value: 8 }
]
Run Code Online (Sandbox Code Playgroud)

这基本上是对前 4 个及其他国家/地区的值进行求和。

我正在将 javascript 与ramdajs一起使用,但到目前为止我只是以一种有点麻烦的方式做到了这一点。

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

cus*_*der 5

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

第 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 }
]
Run Code Online (Sandbox Code Playgroud)

进入这个:

{
  Albania: 4,
  England: 800,
  France: 200,
  Hungary: 3,
  Romania: 500,
  Spain: 130
}
Run Code Online (Sandbox Code Playgroud)

有了这个:

const reducer = reduceBy((sum, {value}) => sum + value, 0);
const reduceCountries = reducer(prop('country'));
Run Code Online (Sandbox Code Playgroud)

第 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 }
]
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式执行此操作:

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

步骤 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 }
  ]
]
Run Code Online (Sandbox Code Playgroud)

你可以用这个来做:

splitAt(-4)
Run Code Online (Sandbox Code Playgroud)

步骤 4:合并第一个子组

[
  [
    { country: "Others", value: 7 }
  ],
  [
    { country: "Spain", value: 130 },
    { country: "France", value: 200 },
    { country: "Romania", value: 500 },
    { country: "England", value: 800 }
  ]
]
Run Code Online (Sandbox Code Playgroud)

有了这个:

over(lensIndex(0), compose(map(countryFromPair), toPairs, reduceOthers));
Run Code Online (Sandbox Code Playgroud)

第 5 步:展平整个阵列

[
  { country: "Others", value: 7 },
  { country: "Spain", value: 130 },
  { country: "France", value: 200 },
  { country: "Romania", value: 500 },
  { country: "England", value: 800 }
]
Run Code Online (Sandbox Code Playgroud)

flatten
Run Code Online (Sandbox Code Playgroud)

完整的工作示例

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)
Run Code Online (Sandbox Code Playgroud)


app*_*ple 2

我尝试了一下并尝试将它的功能用于大多数事情。并保持单一pipe

const f = pipe(
  groupBy(prop('country')),
  map(map(prop('value'))),
  map(sum),
  toPairs(),
  sortBy(prop(1)),
  reverse(),
  addIndex(map)((val, idx) => idx<4?val:['Others',val[1]]),
  groupBy(prop(0)),
  map(map(prop(1))),
  map(sum),
  toPairs(),
  map(([a,b])=>({'country':a,'value':b}))
)
Run Code Online (Sandbox Code Playgroud)

拉姆达 REPL


但是,我认为它没有任何可读性。