ZetCode

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 中的过滤和映射函数。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程