loopsgostructduplicates

Delete Structs with Duplicate Field Values from a Slice of Structs


I have a slice of structs and each struct has two fields. I want to delete a struct from the slice if there is a duplicate value only in the first field. I've tried using loops within loops, maps, and sorting but I can't figure it out.

The closest I've come is deleting a struct from the slice if both fields have the same value as another struct but I need to delete it if the first field has the same value as another struct in the slice.

There are many examples online of doing these when all fields in the struct have the same value but I haven't found any for the case I'm discribing.

The actual program I'm working on is much more complex and it requires that I use a slice of structs.

I've made a simplified example below which gets to the heart of the problem.

It outputs [{one 1} {one 2} {five 5}] The desired output is [{one 1} {five 5}]

Thank you in advance for the help.


import "fmt"

type myKey struct {
    key string
    num int
}

type myKeysList []myKey

func remDupKeys(m myKeysList) myKeysList {
    keys := make(map[myKey]bool)
    list := myKeysList{}
    for _, entry := range m {
        if _, value := keys[entry]; !value {
            keys[entry] = true
            list = append(list, entry)
        }
    }
    return list
}
func main() {

    one := myKey{"one", 1}
    two := myKey{"one", 1}
    three := myKey{"one", 2}
    four := myKey{"one", 1}
    five := myKey{"five", 5}

    myKeysList := myKeysList{one, two, three, four, five}
    fmt.Println(myKeysList)
    uList := remDupKeys(myKeysList)
    fmt.Println(uList)
}

Go Playground Link https://play.golang.org/p/x8sNjW_mxrl


Solution

  • The basic idea in the question is correct: record visited values in a map and skip values already in the map.

    To remove duplicates based a single field in a struct, use the field as the map key:

    func remDupKeys(m myKeysList) myKeysList {
        keys := make(map[string]bool)
        list := myKeysList{}
        for _, entry := range m {
            if _, ok := keys[entry.key]; !ok {
                keys[entry.key] = true
                list = append(list, entry)
            }
        }
        return list
    }