From a9ee294da00683bd3f44e8b35bc1deb1dad8fbda Mon Sep 17 00:00:00 2001 From: lei_lei <96427312+leilei3167@users.noreply.github.com> Date: Sat, 25 Mar 2023 01:35:53 +0800 Subject: [PATCH] perf: New implemention for Diff() (#191) Using set instead of nested for loops, the time complexity is reduced from O(n^2) to O(n) --- v2/diff.go | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/v2/diff.go b/v2/diff.go index 6febbcb..21e2010 100644 --- a/v2/diff.go +++ b/v2/diff.go @@ -9,34 +9,25 @@ package pie // The added and removed returned may be blank respectively, or contain upto as // many elements that exists in the largest slice. func Diff[T comparable](ss []T, against []T) (added, removed []T) { - // This is probably not the best way to do it. We do an O(n^2) between the - // slices to see which items are missing in each direction. - diffOneWay := func(ss1, ss2raw []T) (result []T) { - ss2 := make([]T, len(ss2raw)) - copy(ss2, ss2raw) + set := make(map[T]struct{}, len(ss1)) for _, s := range ss1 { - found := false - - for i, element := range ss2 { - if s == element { - ss2 = append(ss2[:i], ss2[i+1:]...) - found = true - break - } - } + set[s] = struct{}{} + } - if !found { + for _, s := range ss2raw { + if _, ok := set[s]; ok { + delete(set, s) // remove duplicates + } else { result = append(result, s) } } - return } - removed = diffOneWay(ss, against) - added = diffOneWay(against, ss) + added = diffOneWay(ss, against) + removed = diffOneWay(against, ss) return }