[英]How to compose two functions together into 1 using FP's compose() javascript?
How can I compose two functions together into 1 using FP's compose()
here's live code: https://repl.it/JXMl/1 如何使用FP的
compose()
两个函数组合成1个实时代码: https : //repl.it/JXMl/1
I have 3 pure functions: 我有3个纯函数:
// groups By some unique key
const groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
// ungroups the group by
const ungroup = (obj) => {
return Object.keys(obj)
.map(x => obj[x]);
};
// flatten array
const flatten = (arrs) => {
return arrs.reduce((acc, item) => acc.concat(item), [])
}
And a functional utility compose function from Functional Jargon 功能实用程序由Functional Jargon组成函数
const compose = (f, g) => (a) => f(g(a))
In the end, I want a ungroupAndFlatten
function created through compose()
. 最后,我想通过
compose()
创建一个ungroupAndFlatten
函数。
Along the lines of: 沿着:
const ungroupAndFlatten = compose(ungroup, flatten) // Usage doesn't work.
console.log(ungroupAndFlatten(obj))
Example code: 示例代码:
const arrs = [
{name: 'abc', effectiveDate: "2016-01-01T00:00:00+00:00"},
{name: 'abcd', effectiveDate: "2016-02-01T00:00:00+00:00"},
{name: 'abcd', effectiveDate: "2016-09-01T00:00:00+00:00"},
{name: 'abc', effectiveDate: "2016-04-01T00:00:00+00:00"},
{name: 'abc', effectiveDate: "2016-05-01T00:00:00+00:00"},
];
const groupedByName = groupBy(arrs, 'name');
// Example Output
//
// var obj = {
// abc: [
// { name: 'abc', effectiveDate: '2016-01-01T00:00:00+00:00' },
// { name: 'abc', effectiveDate: '2016-04-01T00:00:00+00:00' },
// { name: 'abc', effectiveDate: '2016-05-01T00:00:00+00:00' }
// ],
// abcd: [
// { name: 'abcd', effectiveDate: '2016-02-01T00:00:00+00:00' },
// { name: 'abcd', effectiveDate: '2016-09-01T00:00:00+00:00' }
// ]
// }
const ungroupAndFlatten = compose(ungroup, flatten) // Usage doesn't work.
console.log(ungroupAndFlatten(groupedByName))
// Output:
// var arrs = [
// {name: 'abc', effectiveDate: "2016-01-01T00:00:00+00:00"},
// {name: 'abcd', effectiveDate: "2016-02-01T00:00:00+00:00"},
// {name: 'abcd', effectiveDate: "2016-09-01T00:00:00+00:00"},
// {name: 'abc', effectiveDate: "2016-04-01T00:00:00+00:00"},
// {name: 'abc', effectiveDate: "2016-05-01T00:00:00+00:00"},
// ];
I believe you made a simple mistake,you've set ungroup as your f function while it is your g function: 我相信你犯了一个简单的错误,你将ungroup设置为你的f函数,而它是你的g函数:
const ungroupAndFlatten = compose(flatten, ungroup)
switch ungroup and flatten and everything will work fine 切换取消组合并展平,一切都会正常工作
The function compose
has a evaluation order from right to left . 函数
compose
具有从右到左的评估顺序。
/*
* 1. take x
* 2. execute g(x)
* 3. take the return value of g(x) and execute f with it
*/
const compose = (f, g) => x => f(g(x))
There is another function called pipe
which evaluates from left to right 还有另一个名为
pipe
函数,它从左到右进行求值
const pipe = (g, f) => x => f(g(x))
As already mentioned by @Nima Hakimi , you have reversed the argument order. 正如@Nima Hakimi已经提到的那样 ,你已经颠倒了争论的顺序。
To solve you problem we could 为了解决你的问题我们可以
switch the order of the arguments 切换参数的顺序
\nconst ungroupAndFlatten = compose(const ungroupAndFlatten = compose(\n flatten,
扁平化,\n ungroup
取消组合\n)
)\n
const compose = (f, g) => x => f(g(x)) const ungroup = obj => Object.keys(obj) .map(x => obj[x]); const flatten = arrs => arrs.reduce((acc, item) => acc.concat(item), []) const groupedByName = { abc: [ { name: 'abc', effectiveDate: '2016-01-01T00:00:00+00:00' }, { name: 'abc', effectiveDate: '2016-04-01T00:00:00+00:00' }, { name: 'abc', effectiveDate: '2016-05-01T00:00:00+00:00' } ], abcd: [ { name: 'abcd', effectiveDate: '2016-02-01T00:00:00+00:00' }, { name: 'abcd', effectiveDate: '2016-09-01T00:00:00+00:00' } ] } const ungroupAndFlatten = compose( flatten, ungroup ) console.log( ungroupAndFlatten(groupedByName) )
or use pipe
或使用
pipe
\nconst ungroupAndFlatten = pipe(const ungroupAndFlatten = pipe(\n ungroup,
取消组合,\n flatten
弄平\n)
)\n
const pipe = (g, f) => x => f(g(x)) const ungroup = obj => Object.keys(obj) .map(x => obj[x]); const flatten = arrs => arrs.reduce((acc, item) => acc.concat(item), []) const groupedByName = { abc: [ { name: 'abc', effectiveDate: '2016-01-01T00:00:00+00:00' }, { name: 'abc', effectiveDate: '2016-04-01T00:00:00+00:00' }, { name: 'abc', effectiveDate: '2016-05-01T00:00:00+00:00' } ], abcd: [ { name: 'abcd', effectiveDate: '2016-02-01T00:00:00+00:00' }, { name: 'abcd', effectiveDate: '2016-09-01T00:00:00+00:00' } ] } const ungroupAndFlatten = pipe( ungroup, flatten ) console.log( ungroupAndFlatten(groupedByName) )
n
Arguments n
参数的函数组合 And again we have 我们又一次
\nconst compose = (...fns) => fns.reduceRight((f, g) => (...args) =>const compose =(... fns)=> fns.reduceRight((f,g)=>(... args)=> \n g(f(...args)))
对g(f(...参数)))\n
\nconst pipe = (...fns) => fns.reduce((f, g) => (...args) =>const pipe =(... fns)=> fns.reduce((f,g)=>(... args)=> \n g(f(...args)))
对g(f(...参数)))\n
Our goal is it to compose to ungroup
and flatten
the function groupBy
, too. 我们的目标是组成以
ungroup
和flatten
的功能groupBy
了。
We could try 我们可以试试
const groupByNameAndFlattenAndUngroup = compose(
flatten,
ungroup,
groupBy('name', x) // <-- this is our problem
)
but this will not work. 但这不行。 We can only compose functions with one argument.. The solution is to rewrite
groupBy
to a curried version: 我们只能用一个参数组合的功能。该解决方案是重写
groupBy
到咖喱版本:
const groupBy = xs => key =>
xs.reduce((rv, x) => {
(rv[x[key]] = rv[x[key]] || []).push(x)
return rv
}, {})
const groupByNameAndFlattenAndUngroup = (key, xs) => compose(
flatten,
ungroup,
groupBy ('name')
) (xs)
But this solution can be even shorter. 但是这个解决方案可以更短。 If we switch the order of the arguments from
groupBy
to groupBy = key => xs => {/*..*/}
we can do: 如果我们将参数的顺序从
groupBy
到groupBy = key => xs => {/*..*/}
我们可以这样做:
const groupBy = key => xs =>
xs.reduce((rv, x) => {
(rv[x[key]] = rv[x[key]] || []).push(x)
return rv
}, {})
const groupByNameAndFlattenAndUngroup = compose(
flatten,
ungroup,
groupBy ('name')
)
const arrs = [ {name: 'abc', effectiveDate: "2016-01-01T00:00:00+00:00"}, {name: 'abcd', effectiveDate: "2016-02-01T00:00:00+00:00"}, {name: 'abcd', effectiveDate: "2016-09-01T00:00:00+00:00"}, {name: 'abc', effectiveDate: "2016-04-01T00:00:00+00:00"}, {name: 'abc', effectiveDate: "2016-05-01T00:00:00+00:00"}, ] const compose = (...fns) => fns.reduceRight((f, g) => (...args) => g(f(...args))) const ungroup = obj => Object.keys(obj) .map(x => obj[x]); const flatten = arrs => arrs.reduce((acc, item) => acc.concat(item), []) const groupBy = key => xs => xs.reduce((rv, x) => { (rv[x[key]] = rv[x[key]] || []).push(x) return rv }, {}) const groupByName = groupBy ('name') const groupByEffectiveDate = groupBy ('effectiveDate') const groupByNameAndFlattenAndUngroup = compose( flatten, ungroup, groupByName ) const groupBygroupByEffectiveDateAndFlattenAndUngroup = compose( flatten, ungroup, groupByEffectiveDate ) console.log( groupByNameAndFlattenAndUngroup (arrs) ) console.log( groupBygroupByEffectiveDateAndFlattenAndUngroup (arrs) )
您可以在单个函数中取消组合和展平。
const ungroupAndFlatten = (obj) => Object.keys(obj).reduce((a, k) => {obj[k].forEach(e => a.push(e)); return a}, [])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.