Golang slices.DeleteFunc
最后修改于 2025 年 4 月 20 日
本教程将介绍如何在 Go 中使用 slices.DeleteFunc 函数。我们将通过实际删除元素的示例来讲解切片操作。
slices.DeleteFunc 函数会从切片中移除满足给定条件的元素。它是 Go 实验性 slices 包的一部分。
此函数可用于过滤数据或从集合中移除不需要的元素。它会就地修改切片并返回修改后的切片。
基本的 slices.DeleteFunc 示例
slices.DeleteFunc 最简单的用法是移除切片中的所有负数。我们定义一个测试函数来识别要删除的元素。
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{1, -2, 3, -4, 5}
numbers = slices.DeleteFunc(numbers, func(n int) bool {
return n < 0
})
fmt.Println("Positive numbers:", numbers)
}
我们创建一个包含正数和负数的切片。该函数会移除所有满足条件 (n < 0) 的元素。
删除空字符串
slices.DeleteFunc 可以从切片中过滤掉空字符串。此示例将删除所有空字符串或仅包含空格的字符串。
package main
import (
"fmt"
"slices"
"strings"
)
func main() {
words := []string{"apple", "", "banana", " ", "cherry"}
words = slices.DeleteFunc(words, func(s string) bool {
return strings.TrimSpace(s) == ""
})
fmt.Println("Non-empty words:", words)
}
测试函数使用 strings.TrimSpace 来处理空格。修改后的切片仅包含非空字符串。
使用结构体
我们可以将 slices.DeleteFunc 与自定义结构体类型一起使用。此示例将从切片中移除所有不活跃的用户。
package main
import (
"fmt"
"slices"
)
type User struct {
Name string
Active bool
}
func main() {
users := []User{
{"Alice", true},
{"Bob", false},
{"Charlie", true},
}
users = slices.DeleteFunc(users, func(u User) bool {
return !u.Active
})
fmt.Println("Active users:", users)
}
该函数会检查每个用户的 `Active` 字段。Bob 会被从切片中移除,因为他的 `Active` 状态为 `false`。
删除重复元素
我们可以将 slices.DeleteFunc 与 map 结合使用来删除重复项。此示例仅保留每个唯一数字的第一次出现。
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{1, 2, 2, 3, 4, 4, 4, 5}
seen := make(map[int]bool)
numbers = slices.DeleteFunc(numbers, func(n int) bool {
if seen[n] {
return true
}
seen[n] = true
return false
})
fmt.Println("Unique numbers:", numbers)
}
map 会跟踪已看到的数字,并删除后续的重复项。结果中每个数字只出现一次。
不区分大小写的字符串过滤
此示例演示了如何使用 slices.DeleteFunc 进行不区分大小写的过滤。我们将移除所有 "apple" 的出现。
package main
import (
"fmt"
"slices"
"strings"
)
func main() {
fruits := []string{"Apple", "banana", "APPLE", "cherry", "apple"}
fruits = slices.DeleteFunc(fruits, func(s string) bool {
return strings.EqualFold(s, "apple")
})
fmt.Println("Filtered fruits:", fruits)
}
strings.EqualFold 执行不区分大小写的比较。所有形式的 "apple" 都将被移除,而不考虑其大小写。
性能注意事项
对于大型切片,测试函数的性能至关重要。本示例将比较不同的过滤方法。
package main
import (
"fmt"
"slices"
"time"
)
func main() {
largeSlice := make([]int, 1_000_000)
for i := range largeSlice {
largeSlice[i] = i % 10 // Create repeating pattern
}
// Simple condition
start := time.Now()
_ = slices.DeleteFunc(largeSlice, func(n int) bool {
return n == 5
})
fmt.Println("Simple condition:", time.Since(start))
// Complex condition
start = time.Now()
_ = slices.DeleteFunc(largeSlice, func(n int) bool {
return n > 5 && n % 2 == 0
})
fmt.Println("Complex condition:", time.Since(start))
}
执行时间取决于条件的复杂性和删除的数量。slices.DeleteFunc 由于就地修改切片而效率很高。
实际示例:输入清理
此实际示例使用 slices.DeleteFunc 清理用户输入,移除无效条目。
package main
import (
"fmt"
"slices"
"strconv"
)
func main() {
inputs := []string{"42", "invalid", "15", "99", "not_a_number"}
// First convert to numbers, tracking valid entries
numbers := make([]int, 0, len(inputs))
valid := make([]bool, len(inputs))
for i, s := range inputs {
num, err := strconv.Atoi(s)
if err == nil {
numbers = append(numbers, num)
valid[i] = true
}
}
// Now filter the original slice
inputs = slices.DeleteFunc(inputs, func(s string) bool {
_, err := strconv.Atoi(s)
return err != nil
})
fmt.Println("Valid numbers:", numbers)
fmt.Println("Sanitized inputs:", inputs)
}
我们首先识别无效条目,然后使用 slices.DeleteFunc 移除它们。这展示了实际的数据清理过程。
来源
本教程通过各种场景下过滤切片元素的实际示例,介绍了 Go 中的 slices.DeleteFunc 函数。