亲爱的StackOverflowers ......
我有一组帖子:
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);
我可以通过map& amp找到如何实现我想要的东西。过滤器:
tagsFor(posts).map(function(tag) {
return {
title: tag,
posts: posts.filter(function(post) {
return post.tags.some(t => t === tag);
});
};
});
我似乎无法以默契的方式实现这一目标。
任何指针都会感激不尽......
答案 0 :(得分:3)
我可以看到我目前工作中其他一些答案的影响^ _ ^ @Bergi也给你很好的建议。只需继续制作通用程序并将它们组合在一起。
我似乎无法以默契的方式实现这一目标。
那么目标不应该是完全无点。很多时候,当你稍后再回来时,你会发现非常奇怪的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));
这是utitilies
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)
});
当然,这只是一种方法。如果这有帮助或者您有任何其他问题,请告诉我们!
“不断增加的效用函数集”
拥有大量实用功能可能会让人感到压力,但你应该留意那些感觉你是在复制行为的人。
以此为例......
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
,看看您是否可以删除几个积分。如果你遇到困难,请告诉我。
答案 1 :(得分:0)
非常感谢@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等。但在这种情况下,我认为它不会对任何事情有所帮助。
所以,让我们用B(撰写)挖掘帖子:
const buildTags = comp(
B(map, makeTag)(posts),
collectUniq('tags')
);
现在我们可以看到它是f(x)(g(x))的形式,其中:f = B(map,makeTag); g = collectUniq(&#39; tags');和x =帖子:
const buildTags = S(B(map)(makeTag))(collectUniq('tags'));
现在它是默认的,陈述性的,容易理解(无论如何我想到)
是的,有人给我一杯啤酒,花了我3天! (哎哟)