英文:
Remove element by value in Go list
问题
我有一个元素列表,我想通过值来删除其中一个元素。在Python中,可以这样做:
l = ["apples", "oranges", "melon"]
l.remove("melon")
print(l) # ["apples", "oranges"]
在Go语言中,有一个slice技巧可以通过索引来删除元素,但它不太易读,仍然需要手动找到索引,并且只适用于单个项目类型:
func remove(l []string, item string) {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
}
还有list.List
结构,但它不是通用的,因此需要大量的类型转换才能使用。
从列表中删除元素的惯用方法是什么?
英文:
I have a list of elements and I want to remove one of them, by value. In Python this would be
l = ["apples", "oranges", "melon"]
l.remove("melon")
print(l) # ["apples", "orange"]
What is the equivalent in Go? I found a slice trick to remove an element by index, but it's not very readable, still requires me to find the index manually and only works for a single item type:
func remove(l []string, item string) {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
}
There's the list.List
structure, but it's not generic and thus requires tons of type-castings to use.
What is the idiomatic way of removing an element from a list?
答案1
得分: 23
从列表中删除元素的惯用方法是像你在示例中所做的那样循环遍历它。从切片中按值删除元素在程序中不应该太常见,因为它是一个O(n)
的操作,并且语言中有更好的数据结构来处理这个问题。因此,Go语言没有为切片提供内置的删除函数。
如果你经常使用按值删除元素,请考虑使用集合(set)代替,其中删除和添加元素的时间复杂度为O(1)
,同时仍然可以进行迭代。
set := map[string]bool{"apples": true, "oranges": true, "melon": true}
delete(set, "melon") // 时间复杂度为O(1)
英文:
The idiomatic way to remove an element from a list is to loop through it exactly like you do in your example. Removing an element by value from a slice shouldn't be too common in your program since it is an O(n)
operation and there are better data structures in the language for that. Therefore, Go does not provide a built-in remove function for slices.
If you find yourself using removal by value often, consider using a set instead where removing and adding an element is O(1)
while still being iterable.
set := map[string]bool{"apples":true, "oranges":true, "melon":true}
delete(set,"melon") // is O(1)
答案2
得分: 7
在通用的Go语言(1.18)中,filter函数适用于任何comparable
类型。它只会删除第一个出现的项目。
func remove[T comparable](l []T, item T) []T {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
return l
}
Playground: https://go.dev/play/p/ojlYkvf5dQG?v=gotip
如果你想删除所有出现的项目,可以将不匹配的项目追加到一个新的切片中:
func remove[T comparable](l []T, item T) []T {
out := make([]T, 0)
for _, element := range l {
if element != item {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/W2MerNbh72H
如果切片中的项目不可比较,你可以使用自定义的相等函数进行过滤:
func main() {
list := [][]int{{1, 2}, {2, 2}, {1, 10}}
newlist := remove(list, func(element []int) bool { return element[0] == 1 })
fmt.Println(newlist)
}
func remove[T any](l []T, remove func(T) bool) []T {
out := make([]T, 0)
for _, element := range l {
if !remove(element) {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/qZWoFbM_RUl
英文:
In generic Go (1.18) the filter function works on any comparable
type. It removes only the first occurrence of the item.
func remove[T comparable](l []T, item T) []T {
for i, other := range l {
if other == item {
return append(l[:i], l[i+1:]...)
}
}
return l
}
Playground: https://go.dev/play/p/ojlYkvf5dQG?v=gotip
<hr>
If you want to remove all occurrences, append the items that don't match to a new slice:
func remove[T comparable](l []T, item T) []T {
out := make([]T, 0)
for _, element := range l {
if element != item {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/W2MerNbh72H
<hr>
If the slice items aren't comparable, you can use a custom equality function to filter:
func main() {
list := [][]int{{1, 2}, {2, 2}, {1, 10}}
newlist := remove(list, func(element []int) bool { return element[0] == 1 })
fmt.Println(newlist)
}
func remove[T any](l []T, remove func(T) bool) []T {
out := make([]T, 0)
for _, element := range l {
if !remove(element) {
out = append(out, element)
}
}
return out
}
Playground: https://go.dev/play/p/qZWoFbM_RUl
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论