0

Java Guava Sets.difference behavior:

Known = ["v1","v2"]; Incoming = ["v2","v3","v4"]

incoming = ["v2","v3","v4"]; knownUpdated = ["v2"]

Sets.difference(Known, Incoming) = v1 (To be removed)

Sets.difference(incoming, knownUpdated) = v3,v4 (To be added)

What I have tried in Go is giving the below difference:

Output := [v1 v3 v4] (known, Incoming) 

func Difference(slice1 []string, slice2 []string) []string {
    var diff []string

    for i := 0; i < 2; i++ {
        for _, s1 := range slice1 {
            found := false
            for _, s2 := range slice2 {
                if s1 == s2 {
                    found = true
                    break
                }
            }

            if !found {
                diff = append(diff, s1)
            }
        }
        if i == 0 {
            slice1, slice2 = slice2, slice1
        }
    }

    return diff
}

Its giving symmetric difference but I need the behavior of Guava sets.difference. I know something is wrong with my func. From the guava documentation of public static Sets.SetView difference(Set set1, Set set2):The returned set contains all elements that are contained by set1 and not contained by set2

morganbaz
  • 2,997
  • 1
  • 17
  • 30
Junaid s
  • 89
  • 6

1 Answers1

2

The most straight-forward and easy to understand solution is that of using maps - if you use only the keys, discarding the values, they share similar properties to many other set implementations (O(1) lookup*, unique keys, unordered). At which point, it's actually quite trivial:

func Difference(slice1 []string, slice2 []string) []string {
    // Create proper "set" (Maps have unordered pairs and the keys are unique;
    // lookup to check whether value is present is O(1), similar to other
    // implementations)
    m := make(map[string]struct{}, len(slice1))
    for _, el := range slice1 {
        m[el] = struct{}{}
    }

    // Remove values from slice1 present in slice2
    for _, el := range slice2 {
        delete(m, el)
    }

    // Note that res will be non-deterministic: the order of iteration over maps
    // is made random on purpose by Go itself
    res := make([]string, 0, len(m))
    for k := range m {
        res = append(res, k)
    }
    return res
}

Demo

morganbaz
  • 2,997
  • 1
  • 17
  • 30