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 方法的想法?
(每一步都会得到上一步的输出。最后所有的东西都会放在一起。)
第 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)
我尝试了一下并尝试将它的功能用于大多数事情。并保持单一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)
但是,我认为它没有任何可读性。