简介

集合管道 (Collection pipelines) 是一种编程模式,它让把一些计算 (computation) 组织成一些有序的的操作 (operations) 。这些操作通过将集合作为一个操作的输出 (output) 并将其送入到下一个操作来组成。常见的操作有 filtermapreduce

这种模式在函数式编程中很常见,在具有 lambda 的面向对象语言中也很常见。

集合管道是软件中最常见且令人满意的模式之一。它也会出现在 unix 命令行上,不同的环境有略微不同的形式,常见的操作有不同的名称,但是一旦你熟悉了这种模式,你就会忘不了它。

Unix 下的集合管道模式

现在我们当前工作目录有两个文件:demo.txtdemo1.txt

demo.txt 的内容如下:

123456789
hello
hello

demo1.txt 的内容如下:

hello hello

当我们查找当前目录下所有包含 hello 这个单词的文件时,可以通过下面 grep 命令来达成:

➜ grep -l 'hello' ./*.*
./demo.txt
./demo1.txt

我们还想对每个文件进行单词数统计时,于是我们使用 xargs wc -w 命令:

➜ grep -l 'hello' ./*.* | xargs wc -w
       3 ./demo.txt
       2 ./demo1.txt
       5 total

并且我们还想要按照单词个数排序,所以使用 sort -nr 命令:

➜ grep -l 'hello' ./*.txt | xargs wc -w | sort -nr
       5 total
       3 ./demo.txt
       2 ./demo1.txt

如果只想看前两行并且移除 total,所以继续添加以下命令:

➜ grep -l 'hello' ./*.txt | xargs wc -w | sort -nr | head -2 | tail -1
       3 ./demo.txt

集合

在 Unix 中,集合就是一个文本文件,它的每一行就是集合的每一项,每一行包含若干个由空格分割的值。每个值的含义由其在行中的顺序给出。

这些操作是一个个 Unix 的进程,每个通过管道操作符 (|) 生成的集合,由一个进程的标准输出通过管道传输到下一个进程的标准输入

面向对象 (object-oriented) 编程中的集合就是集合类 (list、array、set 等等) 。

在 JavaScript 语言中,集合管道的简单示例:

[1,2,3,4]
.map((n) => n+ 1)
.filter(n => n > 3)
.reduce((pre, current) => pre + current, 0)
// => 9

常见的操作符

下面是在集合管道中发现的经常使用的操作符。每种语言都对可用的操作以及它们的名称做出不同的选择,但下面试图通过它们的共同功能来看待它们。

map 或 collect

将给定函数应用于输入的每个元素并将结果放入输出。

concat

将集合连接成一个集合。

difference

从管道中删除提供的列表的内容。

distinct

删除重复元素。

drop

一种切片 (slice) 形式,返回除前 n 个元素之外的所有元素。

filter 或 select

在每个元素上运行一个布尔函数,并且只把返回 true 的元素传递到输出。

reject

filter 相反,返回与谓词不匹配的元素。

flat-map 或 mapcat

,在集合上映射一个函数并将结果展平为一级。

flatten (展平)

,从集合中删除嵌套。

reduce 或 fold (折叠) 或 inject

,使用提供的函数来组合输入元素,通常是单个输出值。

group-by

,对每个元素运行一个函数并按结果对元素进行分组。

intersection

,提供一些元素,保留在集合中和他们相同的元素。

slice

,返回给定的第一个和最后一个位置之间的列表子序列。

sort

,输出是基于提供的比较器 (comparator) 的输入的排序副本。

take

返回前 n 个元素的切片 (slice) 形式。

union

,返回该集合或提供的集合中的元素,删除重复项。

参考资料:

> https://martinfowler.com/articles/collection-pipeline/#NestedOperatorExpressions