函数式编程实战(一)

假设有如下测试数据(抓取了阮一峰老师的部分数据,希望阮老师不要介意):

[
  {
    "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判断都没有了,是不是很神奇呢~

原文地址:https://www.cnblogs.com/Farmer-D/p/11778524.html