如何在遍历切片时从切片中删除项目?

新手上路,请多包涵

在切片上范围时从切片中删除项目的最佳方法是什么?

例如:

 type MultiDataPoint []*DataPoint

func (m MultiDataPoint) Json() ([]byte, error) {
    for i, d := range m {
        err := d.clean()
        if ( err != nil ) {
            //Remove the DP from m
        }
    }
    return json.Marshal(m)
}

原文由 Kyle Brandt 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 738
2 个回答

正如您在其他地方提到的,您可以分配新的内存块并仅向其复制有效元素。但是,如果你想避免分配,你可以就地重写你的切片:

 i := 0 // output index
for _, x := range s {
    if isValid(x) {
        // copy and increment index
        s[i] = x
        i++
    }
}
// Prevent memory leak by erasing truncated values
// (not needed if values don't contain pointers, directly or indirectly)
for j := i; j < len(s); j++ {
    s[j] = nil
}
s = s[:i]

完整示例: http ://play.golang.org/p/FNDFswPeDJ

请注意,这将在底层数组中的索引 i 之后保留旧值,因此如果值是或包含指针,这 将泄漏内存,直到切片本身被垃圾收集。您可以通过在截断之前将所有值设置为 nil 或从 i 到切片末尾的零值来解决此问题。

原文由 tomasz 发布,翻译遵循 CC BY-SA 4.0 许可协议

我知道它很久以前就回答了,但我在其他语言中使用了类似的东西,但我不知道这是否是 golang 方式。

只需从后向前迭代,这样您就不必担心删除的索引。我使用与 Adam 相同的示例。

 m = []int{3, 7, 2, 9, 4, 5}

for i := len(m)-1; i >= 0; i-- {
    if m[i] < 5 {
        m = append(m[:i], m[i+1:]...)
    }
}

原文由 autlunatic 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题