How to remove duplicates strings or int from Slice in Go

12,198

Solution 1

I found Burak's and Fazlan's solution helpful. Based on that, I implemented the simple functions that help to remove/filter duplicates data from slices of strings, integers, etc.

Here are my two functions, one for strings and another one for integers of slices. You have to pass your data and return all the unique values as a result.

To remove duplicate strings from slice:

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
}

To remove duplicate integers from slice:

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
}

You can update the slice type, and it will filter out all duplicates data for all types of slices.

Here is the GoPlayground link: https://play.golang.org/p/IyVWlWRQM89

Solution 2

You can do in-place replacement guided with a map:

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]

Solution 3

If you want to don't waste memory allocating another array for copy the values, you can remove in place the value, as following:

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:]...)
}

Result:

Cities before remove: [Mumbai Delhi Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
Cities after remove: [Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
Share:
12,198
Riyaz Khan
Author by

Riyaz Khan

Hi, I am Riyaz, A Senior Frontend Engineer with over five years of experience and have a passion for writing quality, high-performance, and maintainable code following best practices by heart. I have a background in developing many web apps, and in my current company, I am working on banking app, and in previous company worked on fleet management systems that are helping many transports, governments, and school entities. I worked on many features in those apps like monitoring real-time trips, students' check-in and checkout, optimising routes, live locations, live camera streaming, collecting IoT devices data, managing assets, and much more. I have gained most of my experience in the following skills: Vue.JS (2 and 3) NodeJs Vuex Nuxt.JS Javascript SCSS Jest and Cypress Quasar, TailwindCSS, Bootstrap and Element UI HTML &amp; CSS

Updated on June 13, 2022

Comments

  • Riyaz Khan
    Riyaz Khan almost 2 years

    Let's say I have a list of student cities and the size of it could be 100 or 1000, and I want to filter out all duplicates cities.

    I want a generic solution that I can use to remove all duplicate strings from any slice.

    I am new to Go Language, So I tried to do it by looping and checking if the element exists using another loop function.

    Students' Cities List (Data):

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

    Functions that I created, and it's doing the job:

    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
    }
    

    My solution test

    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]
    }
    

    I believe that the above solution that I tried is not an optimum solution. Therefore, I need help from you guys to suggest the fastest way to remove duplicates from the slice?

    I checked StackOverflow, this question is not being asked yet, so I didn't get any solution.