Go 过滤和映射
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中创建和使用过滤和映射函数。
过滤函数处理一个集合,并生成一个新的集合,其中包含给定谓词返回 true 的所有元素。
映射函数将给定的函数应用于集合的每个元素,并将结果返回到一个新集合中。
谓词是一个返回布尔值的单参数函数。
Go 过滤示例
在下一个示例中,我们将过滤函数应用于字符串切片。
main.go
package main
import (
"fmt"
"strings"
)
func filter(data []string, f func(string) bool) []string {
fltd := make([]string, 0)
for _, e := range data {
if f(e) {
fltd = append(fltd, e)
}
}
return fltd
}
func main() {
words := []string{"war", "water", "cup", "tree", "storm"}
p := "w"
res := filter(words, func(s string) bool {
return strings.HasPrefix(s, p)
})
fmt.Println(res)
}
我们有一个单词切片。借助 filter 函数,我们过滤掉所有以“w”开头的单词,并将它们放入一个新的切片中。
func filter(data []string, f func(string) bool) []string {
fltd := make([]string, 0)
for _, e := range data {
if f(e) {
fltd = append(fltd, e)
}
}
return fltd
}
filter 函数以单词切片和谓词作为参数。谓词是应用于每个切片元素的函数。
$ go run main.go [war water]
在下一个示例中,我们过滤结构体类型的切片。
main.go
package main
import "fmt"
type User struct {
name string
occupation string
country string
}
func filter(data []User, f func(User) bool) []User {
fltd := make([]User, 0)
for _, user := range data {
if f(user) {
fltd = append(fltd, user)
}
}
return fltd
}
func main() {
users := []User{
{"John Doe", "gardener", "USA"},
{"Roger Roe", "driver", "UK"},
{"Paul Smith", "programmer", "Canada"},
{"Lucia Mala", "teacher", "Slovakia"},
{"Patrick Connor", "shopkeeper", "USA"},
{"Tim Welson", "programmer", "Canada"},
{"Tomas Smutny", "programmer", "Slovakia"},
}
country := "Slovakia"
res := filter(users, func(u User) bool {
return u.country == country
})
fmt.Println(res)
}
该示例过滤所有居住在斯洛伐克的用户。
$ go run main.go
[{Lucia Mala teacher Slovakia} {Tomas Smutny programmer Slovakia}]
Go 过滤泛型示例
在以下示例中,我们创建了过滤函数的泛型版本。
main.go
package main
import (
"fmt"
"strings"
)
func filter[T any](data []T, f func(T) bool) []T {
fltd := make([]T, 0, len(data))
for _, e := range data {
if f(e) {
fltd = append(fltd, e)
}
}
return fltd
}
func main() {
words := []string{"war", "cup", "water", "tree", "storm"}
res := filter(words, func(s string) bool {
return strings.HasPrefix(s, "w")
})
fmt.Println(res)
vals := []int{-1, 0, 2, 5, -9, 3, 4, 7}
res2 := filter(vals, func(e int) bool {
return e > 0
})
fmt.Println(res2)
}
我们有一个过滤函数的泛型版本。我们用它来过滤字符串和整数。
$ go run main.go [war water] [2 5 3 4 7]
Go 映射示例
在以下示例中,我们转换整数切片。请注意,我们不能将该函数命名为 map,因为它在 Go 中是用于创建字典/映射的关键字。
main.go
package main
import (
"fmt"
)
func map2(data []int, f func(int) int) []int {
mapped := make([]int, len(data))
for i, e := range data {
mapped[i] = f(e)
}
return mapped
}
func main() {
vals := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
res := map2(vals, func(i int) int {
return i * i
})
fmt.Println(res)
}
我们有一个整数切片。我们对切片的所有元素进行平方。
$ go run main.go [1 4 9 16 25 36 49 64 81 100]
在下一个示例中,我们将映射函数应用于字符串切片。
main.go
package main
import (
"fmt"
"strings"
)
func map2(data []string, f func(string) string) []string {
mapped := make([]string, len(data))
for i, e := range data {
mapped[i] = f(e)
}
return mapped
}
func main() {
words := []string{"war", "water", "cup", "tree", "storm"}
res := map2(words, strings.ToUpper)
fmt.Println(res)
}
该示例将字符串切片转换为大写。
$ go run main.go [WAR WATER CUP TREE STORM]
Go 映射泛型示例
在以下示例中,我们有一个映射函数的泛型版本。
main.go
package main
import (
"fmt"
"strconv"
"strings"
)
func map2[T, U any](data []T, f func(T) U) []U {
res := make([]U, 0, len(data))
for _, e := range data {
res = append(res, f(e))
}
return res
}
func main() {
words := []string{"war", "cup", "water", "tree", "storm"}
result := map2(words, func(s string) string {
return strings.ToUpper(s)
})
fmt.Println(result)
fmt.Println("-------------------")
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
squares := map2(numbers, func(n int) int {
return n * n
})
fmt.Println(squares)
fmt.Println("-------------------")
as_strings := map2(numbers, func(n int) string {
return strconv.Itoa(n)
})
fmt.Printf("%q", as_strings)
}
使用映射函数,我们处理整数和字符串。
$ go run main.go [WAR CUP WATER TREE STORM] ------------------- [1 4 9 16 25 36 49 64 81 100] ------------------- ["1" "2" "3" "4" "5" "6" "7" "8" "9" "10"]
来源
The Go Programming Language Specification
在本文中,我们学习了 Golang 中的过滤和映射函数。