【问题标题】:How to remove duplicates strings or int from Slice in Go如何从 Go 中的 Slice 中删除重复的字符串或 int
【发布时间】:2021-06-13 01:42:12
【问题描述】:

假设我有一个学生城市列表,它的大小可能是 100 或 1000,我想过滤掉所有重复的城市

我想要一个通用的解决方案,可以用来从任何切片中删除所有重复的字符串。

我是 Go 语言的新手,所以我尝试通过循环并使用另一个循环函数检查元素是否存在来做到这一点。

学生城市列表(数据):

studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}

我创建的函数,它正在发挥作用:

func contains(s []string, e string) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}

func removeDuplicates(strList []string) []string {
    list := []string{}
    for _, item := range strList {
        fmt.Println(item)
        if contains(list, item) == false {
            list = append(list, item)
        }
    }
    return list
}

我的解决方案测试

func main() {
    studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}

    uniqueStudentsCities := removeDuplicates(studentsCities)
    
    fmt.Println(uniqueStudentsCities) // Expected output [Mumbai Delhi Ahmedabad Bangalore Kolkata Pune]
}

我相信我尝试的上述解决方案不是最佳解决方案。因此,我需要你们的帮助来建议从切片中删除重复项的最快方法?

我检查了 StackOverflow,这个问题还没有被问到,所以我没有得到任何解决方案。

【问题讨论】:

    标签: arrays go slice


    【解决方案1】:

    我发现 Burak'sFazlan's 解决方案很有帮助。在此基础上,我实现了有助于从字符串、整数等切片中删除/过滤重复数据的简单函数。

    这是我的两个函数,一个用于字符串,另一个用于切片整数。您必须传递数据并返回所有唯一值。

    要从切片中删除重复的字符串:

    func removeDuplicateStr(strSlice []string) []string {
        allKeys := make(map[string]bool)
        list := []string{}
        for _, item := range strSlice {
            if _, value := allKeys[item]; !value {
                allKeys[item] = true
                list = append(list, item)
            }
        }
        return list
    }
    

    从切片中删除重复的整数:

    func removeDuplicateInt(intSlice []int) []int {
        allKeys := make(map[int]bool)
        list := []int{}
        for _, item := range intSlice {
            if _, value := allKeys[item]; !value {
                allKeys[item] = true
                list = append(list, item)
            }
        }
        return list
    }
    

    您可以更新切片类型,它会过滤掉所有切片类型的所有重复数据。

    这里是 GoPlayground 链接:https://play.golang.org/p/IyVWlWRQM89

    【讨论】:

      【解决方案2】:

      您可以在地图的指导下进行就地更换:

      processed := map[string]struct{}{}
      w := 0
      for _, s := range cities {
          if _, exists := processed[s]; !exists {
              // If this city has not been seen yet, add it to the list
              processed[s] = struct{}{}
              cities[w] = s
              w++
          }
      }
      cities = cities[:w]
      

      【讨论】:

      • 谢谢,我只是想知道,它是循环 1000 多个城市切片的最佳解决方案吗?
      • 这是一个好方法,直到别人想出更好的方法。
      • 如果你有一个排序的城市列表,你可以在没有地图的情况下做到这一点。在排序数组中,重复项将彼此相邻。如果你真的不想有地图,你可以对城市进行排序,如果你不介意对它们进行排序。可能的优化取决于您的问题。
      【解决方案3】:

      如果您不想浪费内存分配另一个数组来复制值,您可以将值删除,如下所示:

      package main
      
      import "fmt"
      
      var studentsCities = []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
      
      func contains(s []string, e string) bool {
          for _, a := range s {
              if a == e {
                  return true
              }
          }
          return false
      }
      
      func main() {
          fmt.Printf("Cities before remove: %+v\n", studentsCities)
          for i := 0; i < len(studentsCities); i++ {
              if contains(studentsCities[i+1:], studentsCities[i]) {
                  studentsCities = remove(studentsCities, i)
                  i--
              }
          }
          fmt.Printf("Cities after remove: %+v\n", studentsCities)
      }
      func remove(slice []string, s int) []string {
          return append(slice[:s], slice[s+1:]...)
      }
      

      结果:

      Cities before remove: [Mumbai Delhi Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
      Cities after remove: [Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
      

      【讨论】:

      • 根据数据的不同,分配一个新的切片可能比一遍又一遍地不断复制相同的数据更有效。如果顺序无关紧要(问题未指定),请删除带有单独交换的项目。
      【解决方案4】:

      也可以用类似集合的地图来完成:

      ddpStrings := []string{}
      m := map[string]struct{}{}
      
      for _, s := range strings {
          if _, ok := m[scopeStr]; ok {
              continue
          }
          ddpStrings = append(ddpStrings, s)
          m[s] = struct{}{}
      }
      

      【讨论】:

        【解决方案5】:
        func UniqueNonEmptyElementsOf(s []string) []string {
            unique := make(map[string]bool, len(s))
            var us []string
            for _, elem := range s {
                if len(elem) != 0 {
                    if !unique[elem] {
                        us = append(us, elem)
                        unique[elem] = true
                    }
                }
            }
        
            return us
        }
        

        将复制的拼接发送到上述函数,这将返回具有唯一元素的拼接。

        func main() {
            studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
        
            uniqueStudentsCities := UniqueNonEmptyElementsOf(studentsCities)
            
            fmt.Println(uniqueStudentsCities)
        }
        

        【讨论】:

          猜你喜欢
          • 2016-03-08
          • 2016-12-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-30
          相关资源
          最近更新 更多