如何以无点样式映射和过滤它
How do I map & filter this in a point-free style
亲爱的 Whosebugers…
我有一组帖子:
const posts = [
{ title: 'post1', tags: ['all', 'half', 'third', 'quarter', 'sixth']},
{ title: 'post2', tags: ['all', 'half', 'third', 'quarter', 'sixth']},
{ title: 'post3', tags: ['all', 'half', 'third', 'quarter']},
{ title: 'post4', tags: ['all', 'half', 'third']},
{ title: 'post5', tags: ['all', 'half']},
{ title: 'post6', tags: ['all', 'half']},
{ title: 'post7', tags: ['all']},
{ title: 'post8', tags: ['all']},
{ title: 'post9', tags: ['all']},
{ title: 'post10', tags: ['all']},
{ title: 'post11', tags: ['all']},
{ title: 'post12', tags: ['all']}
];
还有一组不断增加的实用函数:
const map = f => list => list.map(f);
const filter = f => list => list.filter(f);
const reduce = f => y => xs => xs.reduce((y,x)=> f(y)(x), y);
const pipe = (fn,...fns) => (...args) => fns.reduce( (acc, f) => f(acc), fn(...args));
const comp = (...fns) => pipe(...fns.reverse()); // const comp = (f, g) => x => f(g(x));
const prop = prop => obj => obj[prop];
const propEq = v => p => obj => prop(p)(obj) === v;
const flatten = reduce(y=> x=> y.concat(Array.isArray(x) ? flatten (x) : x)) ([]);
const unique = list => list.filter((v, i, a) => a.indexOf(v) === i);
const add = a => b => a + b;
const addO = a => b => Object.assign(a, b);
const log = x => console.log(x);
我想将数据按摩成以下格式:
[
{ title: 'sixth', posts: [array of post objects that all have tag 'sixth'] },
{ title: 'quarter', posts: [array of post objects that all have tag 'quarter'] },
{ title: 'third', posts: [array of post objects that all have tag ’third'] },
etc...
]
使用无点样式,仅利用可重复使用的紧凑实用函数。
我可以从所有帖子中获取唯一标签:
const tagsFor = comp(
unique,
flatten,
map(prop('tags'))
);
tagsFor(posts);
我可以弄清楚如何使用地图和过滤器实现我想要的:
tagsFor(posts).map(function(tag) {
return {
title: tag,
posts: posts.filter(function(post) {
return post.tags.some(t => t === tag);
});
};
});
我似乎无法以默契的方式实现这一目标。
如有指点,将不胜感激...
我可以看到我的一些其他答案对您当前工作的影响^_^ @Bergi 也给了您很好的建议。继续制作通用程序并将它们组合在一起。
I just can’t seem to get my head around achieving this in a tacit manner.
好吧,目标不应该是完全无积分。很多时候,你最终会得到非常奇怪的 comp (comp (f))
和 comp (f) (comp (g))
东西,当你稍后回过头来时,这些东西真的很难理解。
我们仍然可以对您的代码进行一些改进
这是我们正在更改的代码
// your original code
tagsFor(posts).map(function(tag) {
return {
title: tag,
posts: posts.filter(function(post) {
return post.tags.some(t => t === tag);
});
};
});
这是更新后的代码
// yay
tagsFor(posts).map(makeTag(posts));
// OR
map (makeTag (posts)) (tagsFor (posts));
这是实用程序
const comp = f => g => x => f (g (x));
const apply = f => x => f (x);
const eq = x => y => y === x;
const some = f => xs => xs.some(apply(f));
const filter = f => xs => xs.filter(apply(f));
const postHasTag = tag => comp (some (eq (tag))) (prop ('tags'));
const makeTag = posts => tag => ({
title: tag,
posts: filter (postHasTag (tag)) (posts)
});
当然这只是一种方法。让我知道这是否有帮助,或者如果您有任何其他问题!
"Ever-increasing set of utility functions"
拥有大量实用功能可能会让人感到不知所措,但您应该注意一些感觉像是在重复行为的功能。
以这个为例...
const propEq = v => p => obj => prop(p)(obj) === v;
3 个参数并不意味着它是一个糟糕的函数,但它至少应该让您三思而后行,并确保它们是必需的。请记住,组合具有更多参数的函数变得更加困难,因此您也应该仔细考虑参数的顺序。无论如何,这个 propEq
函数应该给你一个危险信号。
const eq = x => y => y === x;
const prop = x => y => y[x];
const propEq = p => x => comp (eq(x)) (prop(p))
一旦将 eq
定义为函数,当您在其他函数中遇到不可组合的 ===
时,您应该能够组合它。这适用于 JavaScript.
中的所有运算符
作为一个小挑战,看看你的 reduce
、pipe
和 comp
,看看你是否可以删除几个点。如果您遇到困难,请告诉我。
非常感谢@naomik 的重组和@Berghi 带领我进入组合逻辑的兔子洞,这就是我想出的……
首先,tagsFor 将一些嵌套数组的所有唯一条目收集到一个数组中,这听起来像是通用功能而不是特定于任何特定问题的功能,因此我将其重写为:
const collectUniq = (p) => comp( // is this what flatMap does?
uniq,
flatten,
map(prop(p))
);
所以根据@naomik 的意见我们有:
const hasTag = tag => comp( // somePropEq?
some(eq(tag)),
prop('tags')
);
const makeTag = files => tag => ({
title: tag,
posts: filter (hasTag(tag)) (files)
});
const buildTags = comp(
map(makeTag(posts)),
collectUniq('tags')
);
任何默认解决方案的问题是数据(帖子)被埋在地图中的 makeTag 中。
SKI 演算和 BCKW 逻辑为我们提供了一组有用的组合逻辑函数,我将其保留在这里:
const I = x => x; // id
const B = f => g => x => f(g(x)); // compose <$>
const K = x => y => x; // pure
const C = f => x => y => f(y)(x); // flip
const W = f => x => f(x)(x); // join
const S = f => g => x => f(x)(g(x)); // sub <*>
我们可以将这些别名命名为 id、comp、pure、flip 等。但在这种情况下,我认为这对 grok 没有任何帮助。
所以,让我们用B(撰写)挖掘帖子:
const buildTags = comp(
B(map, makeTag)(posts),
collectUniq('tags')
);
现在我们可以看到它的形式是 f(x)(g(x)) 其中: f = B(map, makeTag); g = collectUniq('标签');和 x = 帖子:
const buildTags = S(B(map)(makeTag))(collectUniq('tags'));
现在它是默认的、声明的并且易于理解(无论如何在我看来)
好吧,有人给我拿了瓶花了我 3 天时间的啤酒! (哎哟)
亲爱的 Whosebugers…
我有一组帖子:
const posts = [
{ title: 'post1', tags: ['all', 'half', 'third', 'quarter', 'sixth']},
{ title: 'post2', tags: ['all', 'half', 'third', 'quarter', 'sixth']},
{ title: 'post3', tags: ['all', 'half', 'third', 'quarter']},
{ title: 'post4', tags: ['all', 'half', 'third']},
{ title: 'post5', tags: ['all', 'half']},
{ title: 'post6', tags: ['all', 'half']},
{ title: 'post7', tags: ['all']},
{ title: 'post8', tags: ['all']},
{ title: 'post9', tags: ['all']},
{ title: 'post10', tags: ['all']},
{ title: 'post11', tags: ['all']},
{ title: 'post12', tags: ['all']}
];
还有一组不断增加的实用函数:
const map = f => list => list.map(f);
const filter = f => list => list.filter(f);
const reduce = f => y => xs => xs.reduce((y,x)=> f(y)(x), y);
const pipe = (fn,...fns) => (...args) => fns.reduce( (acc, f) => f(acc), fn(...args));
const comp = (...fns) => pipe(...fns.reverse()); // const comp = (f, g) => x => f(g(x));
const prop = prop => obj => obj[prop];
const propEq = v => p => obj => prop(p)(obj) === v;
const flatten = reduce(y=> x=> y.concat(Array.isArray(x) ? flatten (x) : x)) ([]);
const unique = list => list.filter((v, i, a) => a.indexOf(v) === i);
const add = a => b => a + b;
const addO = a => b => Object.assign(a, b);
const log = x => console.log(x);
我想将数据按摩成以下格式:
[
{ title: 'sixth', posts: [array of post objects that all have tag 'sixth'] },
{ title: 'quarter', posts: [array of post objects that all have tag 'quarter'] },
{ title: 'third', posts: [array of post objects that all have tag ’third'] },
etc...
]
使用无点样式,仅利用可重复使用的紧凑实用函数。
我可以从所有帖子中获取唯一标签:
const tagsFor = comp(
unique,
flatten,
map(prop('tags'))
);
tagsFor(posts);
我可以弄清楚如何使用地图和过滤器实现我想要的:
tagsFor(posts).map(function(tag) {
return {
title: tag,
posts: posts.filter(function(post) {
return post.tags.some(t => t === tag);
});
};
});
我似乎无法以默契的方式实现这一目标。
如有指点,将不胜感激...
我可以看到我的一些其他答案对您当前工作的影响^_^ @Bergi 也给了您很好的建议。继续制作通用程序并将它们组合在一起。
I just can’t seem to get my head around achieving this in a tacit manner.
好吧,目标不应该是完全无积分。很多时候,你最终会得到非常奇怪的 comp (comp (f))
和 comp (f) (comp (g))
东西,当你稍后回过头来时,这些东西真的很难理解。
我们仍然可以对您的代码进行一些改进
这是我们正在更改的代码
// your original code
tagsFor(posts).map(function(tag) {
return {
title: tag,
posts: posts.filter(function(post) {
return post.tags.some(t => t === tag);
});
};
});
这是更新后的代码
// yay
tagsFor(posts).map(makeTag(posts));
// OR
map (makeTag (posts)) (tagsFor (posts));
这是实用程序
const comp = f => g => x => f (g (x));
const apply = f => x => f (x);
const eq = x => y => y === x;
const some = f => xs => xs.some(apply(f));
const filter = f => xs => xs.filter(apply(f));
const postHasTag = tag => comp (some (eq (tag))) (prop ('tags'));
const makeTag = posts => tag => ({
title: tag,
posts: filter (postHasTag (tag)) (posts)
});
当然这只是一种方法。让我知道这是否有帮助,或者如果您有任何其他问题!
"Ever-increasing set of utility functions"
拥有大量实用功能可能会让人感到不知所措,但您应该注意一些感觉像是在重复行为的功能。
以这个为例...
const propEq = v => p => obj => prop(p)(obj) === v;
3 个参数并不意味着它是一个糟糕的函数,但它至少应该让您三思而后行,并确保它们是必需的。请记住,组合具有更多参数的函数变得更加困难,因此您也应该仔细考虑参数的顺序。无论如何,这个 propEq
函数应该给你一个危险信号。
const eq = x => y => y === x;
const prop = x => y => y[x];
const propEq = p => x => comp (eq(x)) (prop(p))
一旦将 eq
定义为函数,当您在其他函数中遇到不可组合的 ===
时,您应该能够组合它。这适用于 JavaScript.
作为一个小挑战,看看你的 reduce
、pipe
和 comp
,看看你是否可以删除几个点。如果您遇到困难,请告诉我。
非常感谢@naomik 的重组和@Berghi 带领我进入组合逻辑的兔子洞,这就是我想出的……
首先,tagsFor 将一些嵌套数组的所有唯一条目收集到一个数组中,这听起来像是通用功能而不是特定于任何特定问题的功能,因此我将其重写为:
const collectUniq = (p) => comp( // is this what flatMap does?
uniq,
flatten,
map(prop(p))
);
所以根据@naomik 的意见我们有:
const hasTag = tag => comp( // somePropEq?
some(eq(tag)),
prop('tags')
);
const makeTag = files => tag => ({
title: tag,
posts: filter (hasTag(tag)) (files)
});
const buildTags = comp(
map(makeTag(posts)),
collectUniq('tags')
);
任何默认解决方案的问题是数据(帖子)被埋在地图中的 makeTag 中。
SKI 演算和 BCKW 逻辑为我们提供了一组有用的组合逻辑函数,我将其保留在这里:
const I = x => x; // id
const B = f => g => x => f(g(x)); // compose <$>
const K = x => y => x; // pure
const C = f => x => y => f(y)(x); // flip
const W = f => x => f(x)(x); // join
const S = f => g => x => f(x)(g(x)); // sub <*>
我们可以将这些别名命名为 id、comp、pure、flip 等。但在这种情况下,我认为这对 grok 没有任何帮助。
所以,让我们用B(撰写)挖掘帖子:
const buildTags = comp(
B(map, makeTag)(posts),
collectUniq('tags')
);
现在我们可以看到它的形式是 f(x)(g(x)) 其中: f = B(map, makeTag); g = collectUniq('标签');和 x = 帖子:
const buildTags = S(B(map)(makeTag))(collectUniq('tags'));
现在它是默认的、声明的并且易于理解(无论如何在我看来)
好吧,有人给我拿了瓶花了我 3 天时间的啤酒! (哎哟)