在Go列表中按值删除元素

oknrviil  于 2022-12-07  发布在  Go
关注(0)|答案(2)|浏览(201)

我有一个元素列表,我想删除其中的一个,按值。

l = ["apples", "oranges", "melon"]
l.remove("melon")
print(l) # ["apples", "orange"]

我找到了一个slice trick,它可以通过索引删除一个元素,但它的可读性不是很好,仍然需要我手动查找索引,并且只对单个项类型有效:

func remove(l []string, item string) {
    for i, other := range l {
        if other == item {
            return append(l[:i], l[i+1:]...)
        }
    }
}

list.List结构,但它不是通用的,因此需要大量的类型转换来使用。
从列表中删除元素的惯用方法是什么?

y1aodyip

y1aodyip1#

从列表中移除元素的惯用方法是循环遍历列表,就像你在示例中所做的那样。从切片中按值移除元素在你的程序中不应该太常见,因为这是一个O(n)操作,在语言中有更好的数据结构。因此,Go语言没有为切片提供内置的移除函数。
如果你发现自己经常使用按值移除,考虑使用一个集合,其中移除和添加一个元素是O(1),同时仍然是可迭代的。

set := map[string]bool{"apples":true, "oranges":true, "melon":true}
delete(set,"melon") // is O(1)
tmb3ates

tmb3ates2#

在泛型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

相关问题