假设有如下测试数据(抓取了阮一峰老师的部分数据,希望阮老师不要介意):
[ { "title": "周刊", "href": "http://www.ruanyifeng.com/blog/weekly/", "categories": [ { "title": "科技爱好者周刊:第 80 期", "href": "http://www.ruanyifeng.com/blog/2019/11/weekly-issue-80.html", "publishTime": "2019-11-01", "commentCounts": 18 }, { "title": "科技爱好者周刊:第 79 期", "href": "http://www.ruanyifeng.com/blog/2019/10/weekly-issue-79.html", "publishTime": "2019-10-25", "commentCounts": 44 } ] }, { "title": "创业", "href": "http://www.ruanyifeng.com/blog/startup/", "categories": [ { "title": "谷歌的绩效管理", "href": "http://www.ruanyifeng.com/blog/2016/03/performance-management.html", "publishTime": "2016-03-29", "commentCounts": 19 }, { "title": "七个对我最重要的职业建议(译文)", "href": "http://www.ruanyifeng.com/blog/2015/09/career-advice.html", "publishTime": "2015-09-18", "commentCounts": 47 } ] } ]
然后我们需要处理如下问题:获取2019年评论最多的文章的名称
假设我们以命令式的编程思想来处理这个问题,那可能需要这样来解决:
1 // data 为上述数据 2 var maxCount = 0; 3 var maxTitle = ''; 4 for (let i = 0; i < data.length; ++i) { 5 let categories = data[i].categories; 6 for (let j = 0; j < categories.length; ++j) { 7 let cat = categories[j]; 8 if (cat.publishTime < '2019-01-01') { 9 continue; 10 } 11 12 if (maxCount < cat.commentCounts) { 13 maxCount = cat.commentCounts, 14 maxTitle = cat.title 15 } 16 } 17 } 18 19 console.log(`title: ${maxTitle}, comments: ${maxCount}`); 20 // => title: 科技爱好者周刊:第 79 期, comments: 44
然后我们以函数式的思想来解决这个问题:
1 var R = require('ramda'); 2 3 // 文章列表保存在categories中, 所以首先我们要取这个属性 4 var getCates = R.map(R.prop('categories')); 5 // console.log(getCates(data)); // 这时输出的格式是一个二维数组: [[...], [...]] 6 7 // 我们需要将二维数组展开成一维数组 8 var unnestCates = R.compose(R.unnest, getCates); 9 // console.log(unnestCates(data)) // 这时我们就得到一个文章列表的一维数组了 10 11 // 接下去我们需要找出2019年发表的文章 12 var timeGt2019 = R.compose(R.lt('2019-01-01'), R.prop('publishTime')); 13 var getGt2019Cates = R.compose(R.filter(timeGt2019), unnestCates); 14 // console.log(getGt2019Cates(data)); 15 16 // 然后我们对数组元素按照评论数进行降序排序 17 var descSort = R.sort(R.descend(R.prop('commentCounts'))); 18 var getSorted2019Cates = R.compose(descSort, getGt2019Cates); 19 // console.log(getSorted2019Cates(data)); 20 21 // 最后我们只需要取出数组的第一个元素即可 22 var result = R.head(getSorted2019Cates(data)); 23 24 console.log(`title: ${result.title}, comments: ${result.commentCounts}`); 25 // => title: 科技爱好者周刊:第 79 期, comments: 44
可以看到我们获取到了正确的结果,接下去再对上面的代码进行简化:
1 var R = require('ramda'); 2 var getMostCommentsCatIn2019 = R.compose( 3 R.head, 4 R.sort(R.descend(R.prop('commentCounts'))), 5 R.filter( 6 R.compose( 7 R.lt('2019-01-01'), 8 R.prop('publishTime')) 9 ), 10 R.compose( 11 R.unnest, 12 R.map(R.prop('categories')) 13 ) 14 ); 15 16 var result = getMostCommentsCatIn2019(data); 17 console.log(`title: ${result.title}, comments: ${result.commentCounts}`);
到此为止已经全部结束,大家可以看到使用函数式后,所有的循环和if判断都没有了,是不是很神奇呢~