从切片中移除项目的最佳方法是什么?
例如:
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)
}
答案 0 :(得分:33)
正如您在其他地方提到的,您可以分配新的内存块并仅将有效元素复制到其中。但是,如果要避免分配,可以就地重写切片:
i := 0 // output index
for _, x := range s {
if isValid(x) {
// copy and increment index
s[i] = x
i++
}
}
s = s[:i]
完整示例:http://play.golang.org/p/FNDFswPeDJ
请注意,它会在基础数组中的索引i
之后留下一些垃圾,因此请确保没有其他切片在其中使用它。
答案 1 :(得分:13)
可能有更好的方法,但这是一个从切片中删除偶数值的示例:
m := []int{1,2,3,4,5,6}
deleted := 0
for i := range m {
j := i - deleted
if (m[j] & 1) == 0 {
m = m[:j+copy(m[j:], m[j+1:])]
deleted++
}
}
请注意,我没有使用i, d := range m
语法获取元素,因为一旦开始从切片中删除,d
最终会被设置为错误的元素。
答案 2 :(得分:11)
我知道很久以前的答案,但我在其他语言中使用这样的东西,但我不知道它是否是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:]...)
}
}
答案 3 :(得分:5)
另一个选项是使用切片长度的正常for循环,并在每次删除值时从索引中减去1。请参阅以下示例:
m := []int{3, 7, 2, 9, 4, 5}
for i := 0; i < len(m); i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
i-- // -1 as the slice just got shorter
}
}
我不知道len()
是否使用了足够的资源来做出任何改变,但您也可以只运行一次并从长度值中减去:
m := []int{3, 7, 2, 9, 4, 5}
for i, s := 0, len(m); i < s; i++ {
if m[i] < 5 {
m = append(m[:i], m[i+1:]...)
s--
i--
}
}
答案 4 :(得分:2)
类似的东西:
m = append(m[:i], m[i+1:]...)
答案 5 :(得分:1)
这是从片段中删除元素的更惯用的Go方法。
temp := s[:0]
for _, x := range s {
if isValid(x) {
temp = append(temp, x)
}
}
s = temp
游乐场链接:https://play.golang.org/p/OH5Ymsat7s9
注意:示例和游乐场链接基于@tomasz的答案https://stackoverflow.com/a/20551116/12003457
答案 6 :(得分:0)
您甚至不需要向后计数,但确实需要检查您是否在阵列的末尾,建议的append()
将失败。这是从排序列表中删除重复正整数的示例:
// Remove repeating numbers
numbers := []int{1, 2, 3, 3, 4, 5, 5}
log.Println(numbers)
for i, numbersCount, prevNum := 0, len(numbers), -1; i < numbersCount; numbersCount = len(numbers) {
if numbers[i] == prevNum {
if i == numbersCount-1 {
numbers = numbers[:i]
} else {
numbers = append(numbers[:i], numbers[i+1:]...)
}
continue
}
prevNum = numbers[i]
i++
}
log.Println(numbers)
答案 7 :(得分:0)
示例:
package main
import (
"fmt"
"sort"
)
func main() {
// Our slice.
s := []int{3, 7, 2, 9, 4, 5}
// 1. Iterate over it.
for i, v := range s {
func(i, v int) {}(i, v)
}
// 2. Sort it. (by whatever condition of yours)
sort.Slice(s, func(i, j int) bool {
return s[i] < s[j]
})
// 3. Cut it only once.
i := sort.Search(len(s), func(i int) bool { return s[i] >= 5 })
s = s[i:]
// That's it!
fmt.Println(s) // [5 7 9]
}
答案 8 :(得分:0)
我只是实现了一种方法,该方法可以删除slice中的所有nil元素。
我用它来解决leetcode问题,它运行良好。
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNil(lists *[]*ListNode) {
for i := 0; i < len(*lists); i++ {
if (*lists)[i] == nil {
*lists = append((*lists)[:i], (*lists)[i+1:]...)
i--
}
}
}