删除字符串切片中的相邻重复项

Remove Adjacent Duplicates in string slice

我有问题要 write an in-place function to eliminate the adjacent duplicates in a string slice.

我想出了下面的代码

func main() {
    tempData := []string{"abc", "abc", "abc", "def", "def", "ghi"}
    removeAdjacentDuplicates(tempData)
    fmt.Println(tempData)
}

func removeAdjacentDuplicates(data []string) {
    for j := 1; j < len(data); {
        if data[j-1] == data[j] {
            data = append(data[:j], data[j+1:]...)
        } else {
            j++
        }
    }
    fmt.Println(data)
}

输出如下

[abc def ghi]
[abc def ghi ghi ghi ghi]

我的疑问是,如果在函数中修改了 slice,那么在调用函数中,为什么 slice 没有给出正确的结果? 此外,任何能更好地理解 slices(和底层 array)的文章都会非常有帮助。

在您的代码中,removeAdjacentDuplicates 想要改变参数中传递的 slcie。这真的不可能。

这个函数应该 return 新切片,就像 append 一样。

func removeAdjacentDuplicates(data []string) []string{
    for j := 1; j < len(data); {
        if data[j-1] == data[j] {
            data = append(data[:j], data[j+1:]...)
        } else {
            j++
        }
    }
    return data
}

如果你真的想改变参数,这是可能的,但你需要传递一个指向切片的指针*[]string

函数 removeAdjacentDuplicate 获取切片“就好像”它是对 tempData 的引用

main()中tempData的容量和长度在整个生命周期内保持不变 节目

在 removeAdjacentDuplicate 函数中,每次找到一个 dupe 时,“ghi”的最终值从末尾移动到末尾 - 1。因此在 切片有重复的“ghi”

当控制returns到main时,程序打印出now modified 切片临时数据。因为它以类似的方式传递给对 功能是修改了这段内存。函数调用没有复制内存

您可以在程序运行时通过查看 cap() 和 len() 来了解此行为

package main

import (
        "fmt"
)

func main() {
        tempData := []string{"abc", "abc", "abc", "def", "def", "ghi"}
        removeAdjacentDuplicates(tempData)
        fmt.Println(tempData,cap(tempData),len(tempData))
}

func removeAdjacentDuplicates(data []string) {
        for j := 1; j < len(data); {
                if data[j-1] == data[j] {
                        data = append(data[:j], data[j+1:]...)
        fmt.Println(data,cap(data),len(data))
                } else {
                        j++
                }
        }
        fmt.Println(data, cap(data),len(data))
}

试试这个功能:

func deleteAdjacentDuplicate(slice []string) []string {
    for i := 1; i < len(slice); i++ {
        if slice[i-1] == slice[i] {
            copy(slice[i:], slice[i+1:]) //copy [4] where there is [3, 4] => [4, 4]
            slice = slice[:len(slice)-1] //removes last element
            i-- //avoid advancing counter
        }
    }
    return slice
}