Go 过滤切片
最后修改时间 2024 年 4 月 11 日
在本文中,我们将展示如何在 Golang 中过滤切片。
过滤操作会处理数据结构(例如数组),并生成一个新的数据结构,其中只包含给定谓词返回 true 的元素。
谓词是一个返回布尔值的单参数函数。
Go 过滤切片示例
在下面的示例中,我们过滤掉正数。
positive.go
package main
import (
"fmt"
)
func main() {
vals := []int{-2, 0, 1, 9, 7, -3, -5, 6}
positive := []int{}
for i := range vals {
if vals[i] > 0 {
positive = append(positive, vals[i])
}
}
fmt.Println(positive)
}
我们有一个整数切片。我们从现有切片创建一个新切片,其中只包含其正值。
for i := range vals {
if vals[i] > 0 {
positive = append(positive, vals[i])
}
}
我们使用 for 循环遍历数组的元素。我们测试每个元素是否大于零。所有满足条件的元素都会被复制到新的 positive 切片中。原始切片不会被修改。
$ go run simple.go [1 9 7 6]
Go 原地过滤切片
在下面的示例中,切片在过滤操作期间被修改。
positive.go
package main
import (
"fmt"
)
func main() {
vals := []int{-2, 0, 1, 9, 7, -3, -5, 6}
n := 0
for _, val := range vals {
if isPositive(val) {
vals[n] = val
n++
}
}
vals = vals[:n]
fmt.Println(vals)
}
func isPositive(val int) bool {
if val > 0 {
return true
} else {
return false
}
}
该示例修改了 vals 切片,使其只包含正值。没有创建新的切片。
Go 按字符串长度过滤切片
在下面的示例中,我们按字符串长度进行过滤。
fil_strlen.go
package main
import (
"fmt"
)
func main() {
words := []string{"sky", "forest", "fly", "cup", "wood",
"falcon", "so", "see", "tool"}
filtered := []string{}
for i := range words {
if len(words[i]) == 3 {
filtered = append(filtered, words[i])
}
}
fmt.Println(filtered)
}
在过滤操作中,我们只包含长度为三个字符的单词。
$ go run fil_strlen.go [sky fly cup see]
Go 过滤结构体切片
在下面的示例中,我们过滤结构体切片。
filter_slice_structs.go
package main
import "fmt"
type User struct {
name string
occupation string
country string
}
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"},
}
var programmers []User
for _, user := range users {
if isProgrammer(user) {
programmers = append(programmers, user)
}
}
fmt.Println("Programmers:")
for _, u := range programmers {
fmt.Println(u)
}
}
func isProgrammer(user User) bool {
return user.occupation == "programmer"
}
我们有一个用户切片。我们创建一个新的切片,其中只包含程序员。
for _, user := range users {
if isProgrammer(user) {
programmers = append(programmers, user)
}
}
我们遍历 users 切片,如果用户满足 isProgrammer 断言,则将当前用户添加到 programmers 切片中。
func isProgrammer(user User) bool {
return user.occupation == "programmer"
}
IsProgrammer 断言对于所有 occupation 字段等于 "programmer" 的用户都返回 true。
$ go run filter_slice_structs.go
Programmers:
{Paul Smith programmer Canada}
{Tim Welson programmer Canada}
{Tomas Smutny programmer Slovakia}
Go 过滤切片通用示例
下一个示例有一个更通用的过滤函数。
generic.go
package main
import (
"fmt"
"strings"
)
func main() {
words := []string{"sky", "forest", "fly", "cup", "wood",
"falcon", "so", "see", "tool"}
filtered := Filter(words, func(word string) bool {
return strings.HasPrefix(word, "s")
})
fmt.Println(filtered)
filtered2 := Filter(words, func(word string) bool {
return len(word) == 3
})
fmt.Println(filtered2)
}
func Filter(vs []string, f func(string) bool) []string {
filtered := make([]string, 0)
for _, v := range vs {
if f(v) {
filtered = append(filtered, v)
}
}
return filtered
}
我们有一个单词切片。我们通过字符串前缀和字符串长度来过滤切片。
$ go run fil_strlen2.go [sky so see] [sky fly cup see]
来源
The Go Programming Language Specification
在本文中,我们过滤了 Go 中的切片。