GO编程模式学习笔记:MAP-REDUCE

GO编程模式学习笔记系列为学习陈皓的GO编程模式系列文章记录与心得。
原文链接:GO编程模式:MAP-REDUCE

Map

func MapStrToStr(arr []string, fn func(s string) string) []string {
    var newArray = []string{}
    for _, it := range arr {
        newArray = append(newArray, fn(it))
    }
    return newArray
}

var list = []string{"Hao", "Chen", "MegaEase"}
x := MapStrToStr(list, func(s string) string {
    return strings.ToUpper(s)
})
fmt.Printf("%v\n", x)
//["HAO", "CHEN", "MEGAEASE"]

MapStrToInt将如何从一个string变成另外string的实现交给了调用方。可以是转换为大写或者小写,甚至可以不转换返回原来字符串。

Map的模式在一个过程中反复需要同样签名的函数的时候能简化代码。实际上传入map的函数可以认为是一个接口。如果一个遍历过程传一个接口更合适,就可以考虑使用map方式简化代码。

Reduce

func Reduce(arr []string, fn func(s string) int) int {
    sum := 0
    for _, it := range arr {
        sum += fn(it)
    }
    return sum
}

var list = []string{"Hao", "Chen", "MegaEase"}

x := Reduce(list, func(s string) int {
    return len(s)
})
fmt.Printf("%v\n", x)
// 15

Reduce适合把一个集合变成一个标量,比如计算长度和,平均数等统计值。

Filter

func Filter(arr []int, fn func(n int) bool) []int {
    var newArray = []int{}
    for _, it := range arr {
        if fn(it) {
            newArray = append(newArray, it)
        }
    }
    return newArray
}
var intset = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
out := Filter(intset, func(n int) bool {
   return n%2 == 1
})
fmt.Printf("%v\n", out)
out = Filter(intset, func(n int) bool {
    return n > 5
})
fmt.Printf("%v\n", out)

Filter是对单个元素的处理。

Map-Filter-Reduce组合起来是一个模式,可以用一张图表示:
GO编程模式学习笔记:MAP-REDUCE
Map/Reduce/Filter只是一种控制逻辑,真正的业务逻辑是在传给他们的数据和那个函数来定义的。是的,这是一个很经典的“业务逻辑”和“控制逻辑”分离解耦的编程模式。

泛型Map-Filter-Reduce,太复杂了不学了,不如使用代码生成手段。

以下引用了作者和网友对这个模式的理解:

在全世界范围内,有大量的程序员都在问Go语言官方什么时候在标准库中支持 Map/Reduce,Rob Pike说,这种东西难写吗?还要我们官方来帮你们写么?这种代码我多少年前就写过了,但是,我从来一次都没有用过,我还是喜欢用“For循环”,我觉得你最好也跟我一起用 “For循环”。

评论引用:
for 循环相比之下,一个问题是,思考的方式低了一个层级。另一方面,for 循环能做更多奇奇怪怪的事情,所以语义可以很复杂。
而 map / filter / reduce 是相当好理解的:先变换,再过滤,最后总结。不管你每一步的操作多么复杂,其复杂性都被分离开了,而不会纠缠在一起,让人迷失方向。

上一篇:【每日函数】每日函数(2021.08.07)


下一篇:Shell脚本的基本知识点整理-3