【问题标题】:Remove Adjacent Duplicates in string slice删除字符串切片中的相邻重复项
【发布时间】:2021-08-04 09:49:25
【问题描述】:

我有一个问题声明给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]

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

【问题讨论】:

  • 另外,data = append(data[:j], data[j+1:]...) 正在复制大量数据(切片的其余部分),这可能会破坏性能。您可以稍微改变一下,并通过在适当的位置附加单个项目来避免它。

标签: arrays go slice


【解决方案1】:

函数 removeAdjacentDuplicate 将切片“当作”它是对 tempData 的引用

main() 中 tempData 的容量和长度在生命周期内保持不变 程序的

在 removeAdjacentDuplicate 函数中,每次发现一个骗子时,“ghi”的最终值都会从末尾移动到末尾 - 1。所以在内存末尾 切片中有重复的“ghi”

当控件返回主程序时,程序打印出现在修改的 切片临时数据。因为它以类似的方式传递给对 功能是修改了这个内存。函数调用没有复制内存

您可以通过查看程序运行时的 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))
}

【讨论】:

    【解决方案2】:

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

    这个函数应该返回新的切片,就像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

    【讨论】:

      【解决方案3】:

      试试这个功能:

      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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-05
        • 2017-04-16
        • 1970-01-01
        • 2016-03-08
        • 2015-11-29
        • 2021-09-29
        相关资源
        最近更新 更多