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