Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何在切片上进行扫描时从切片中删除项目?_Go - Fatal编程技术网

Go 如何在切片上进行扫描时从切片中删除项目?

Go 如何在切片上进行扫描时从切片中删除项目?,go,Go,在切片上搜索时,从切片中删除项目的最佳方法是什么 例如: 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 } } retu

在切片上搜索时,从切片中删除项目的最佳方法是什么

例如:

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)
}
比如:

m = append(m[:i], m[i+1:]...)

可能有更好的方法,但下面是一个从切片中删除偶数值的示例:

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
将最终被设置为错误的元素。

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

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]
i:=0//输出索引
对于ux:=范围s{
如果有效(x){
//复制和增量索引
s[i]=x
我++
}
}
//通过擦除截断的值防止内存泄漏
//(如果值不直接或间接包含指针,则不需要)
对于j:=i;j
完整示例:


注意,这将在底层数组中的索引
i
之后保留旧值,因此,如果值是指针或包含指针,则这将一直保留到片段本身被垃圾回收为止。您可以通过将所有值设置为nil或从i到切片结束的零值,然后再截断切片来解决此问题。

另一个选项是使用切片长度使用法线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
    }
}

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

只需从后向前迭代,就不必担心索引被删除。我用的是和亚当一样的例子

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:]...)
    }
}
m=[]int{3,7,2,9,4,5}
对于i:=len(m)-1;i>=0;我--{
如果m[i]<5{
m=追加(m[:i],m[i+1:]…)
}
}

您甚至不需要倒数,但您需要检查您是否位于建议的
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)
//删除重复的数字
数字:=[]整数{1,2,3,3,4,5,5}
log.Println(数字)
对于i,numberscont,prevNum:=0,len(数字),-1;我是数数的;numberscont=len(数字){
如果数字[i]==prevNum{
如果i==numbersCount-1{
数字=数字[:i]
}否则{
数字=附加(数字[:i],数字[i+1:]…)
}
持续
}
prevNum=数字[i]
我++
}
log.Println(数字)
操场:

试试看

例如:

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]
}
主程序包
进口(
“fmt”
“排序”
)
func main(){
//我们的那一片。
s:=[]int{3,7,2,9,4,5}
//1.迭代它。
对于i,v:=范围s{
func(i,v int){}(i,v)
}
//2.分类。(根据你的情况)
sort.Slice(s,func(i,j int)bool{
返回s[i]=5})
s=s[i:]
//就这样!
fmt.Println(s)/[5 7 9]
}

我刚刚实现了一个方法,它删除了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--
        }
    }
}
/**
*单链表的定义。
*类型ListNode结构{
*Val int
*下一个*列表节点
* }
*/
func removeNil(列表*[]*列表节点){
对于i:=0;i
这里有一种更惯用的方法来从片中删除元素

temp := s[:0]
for _, x := range s {
    if isValid(x) {
        temp = append(temp, x)
    }
}
s = temp
游乐场连接:


注意:示例和游乐场链接基于@tomasz的答案。

@YasirG.:用于从
地图中删除。OP想要从
切片中删除
。啊,真的很抱歉,错误的答案已经醒了25个小时了:SGo迫切需要一个下降范围构造。没有它会导致大量的额外工作。这会改变什么呢@Vector虽然我刚刚意识到,仅仅创建第二个多数据点对象,向其添加有效的内容,并封送它,是非常直接的(可能效率更低?)。我不知道为什么我一开始没有看到这一点:-/我想效率取决于预期的删除与元素总数的比率。不过,代码很可能更直接。
对于i来说,
应该是
对于i:=
@newacct:Oops。已编辑。对于i:=0,应使用形式
;i
对于循环,范围可能会给您一个
索引超出范围的错误。值得注意的是:我试图在字符串片上使用此方法-我得到此错误:“不能在append中使用m[i+1:](type[]string)作为类型字符串”第二个参数似乎是一个字符串而不是一片字符串。有什么想法吗?Nvmd-我刚刚意识到“…”实际上是代码的一部分。如果在迭代
m
时使用此参数,您将得到
运行时错误:切片超出范围
。这就是问题所在。您可以使用
m=append(m[:I],m][i+1:]…)
从切片中删除项目,但在使用i的
进行迭代时不删除,元素:=范围m
。在Go@Ectomorph然后,我是一个C++程序员——幸好这些日子已经过去了,用它们来分号。应该是被接受的答案。比每次删除时复制数组要好得多。@masz你愿意详细说明你的
注释的含义吗?它会留下一些垃圾
句子吗?@EugeneBeresovsky我认为我的措辞不太准确,我唯一的意图是警告人们我们正在覆盖原始数组,所以可能会有副作用。将进行编辑。问得好,但我想不起为什么会有。可能只是为了展示某种功能作为一个
temp := s[:0]
for _, x := range s {
    if isValid(x) {
        temp = append(temp, x)
    }
}
s = temp