Skip to content

Commit

Permalink
perf(utils): optimize slice functions (#132)
Browse files Browse the repository at this point in the history
* perf(utils): optimize slice functions

* test(utils): added tests for SimplifyHDRSlice
  • Loading branch information
nuxencs authored Aug 25, 2024
1 parent 8ace2b4 commit 7a3aa64
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 28 deletions.
8 changes: 4 additions & 4 deletions internal/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ func compareReleases(r1, r2 rls.Release, fuzzyMatching domain.FuzzyMatching) int
return 203
}

if !utils.CompareStringSlices(r1.Cut, r2.Cut) {
if !utils.EqualElements(r1.Cut, r2.Cut) {
return 204
}

if !utils.CompareStringSlices(r1.Edition, r2.Edition) {
if !utils.EqualElements(r1.Edition, r2.Edition) {
return 205
}

// skip comparing repack status when skipRepackCompare is enabled
if !fuzzyMatching.SkipRepackCompare {
if !utils.CompareStringSlices(r1.Other, r2.Other) {
if !utils.EqualElements(r1.Other, r2.Other) {
return 206
}
}
Expand All @@ -57,7 +57,7 @@ func compareReleases(r1, r2 rls.Release, fuzzyMatching domain.FuzzyMatching) int
r2.HDR = utils.SimplifyHDRSlice(r2.HDR)
}

if !utils.CompareStringSlices(r1.HDR, r2.HDR) {
if !utils.EqualElements(r1.HDR, r2.HDR) {
return 207
}

Expand Down
43 changes: 23 additions & 20 deletions internal/utils/slices.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,46 @@
package utils

import (
"slices"
"strings"
)

func DedupeSlice[T comparable](s []T) []T {
inResult := make(map[T]bool)
var result []T
for _, str := range s {
if _, ok := inResult[str]; !ok {
inResult[str] = true
result = append(result, str)
}
resultSet := make(map[T]struct{})
for _, i := range s {
resultSet[i] = struct{}{}
}

result := make([]T, 0, len(resultSet))
for str := range resultSet {
result = append(result, str)
}

return result
}

func CompareStringSlices(x, y []string) bool {
func EqualElements[T comparable](x, y []T) bool {
if len(x) != len(y) {
return false
}

sortedX := slices.Clone(x)
sortedY := slices.Clone(y)
freqMap := make(map[T]int)
for _, i := range x {
freqMap[i]++
}

slices.Sort(sortedX)
slices.Sort(sortedY)
for _, i := range y {
if freqMap[i] == 0 {
return false
}
freqMap[i]--
}

return slices.Equal(sortedX, sortedY)
return true
}

func SimplifyHDRSlice(hdrSlice []string) []string {
if len(hdrSlice) == 0 {
return hdrSlice
}

for i, v := range hdrSlice {
if strings.Contains(v, "HDR") {
for i := range hdrSlice {
if strings.Contains(hdrSlice[i], "HDR") {
hdrSlice[i] = "HDR"
}
}
Expand Down
126 changes: 122 additions & 4 deletions internal/utils/slices_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func Test_DedupeSlice(t *testing.T) {
{
name: "string_slice_empty",
slice: []string{},
want: []string(nil),
want: []string{},
},
{
name: "int_slice_some_duplicates",
Expand All @@ -53,19 +53,137 @@ func Test_DedupeSlice(t *testing.T) {
{
name: "int_slice_empty",
slice: []int{},
want: []int(nil),
want: []int{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch v := tt.slice.(type) {
case []string:
assert.Equalf(t, tt.want, DedupeSlice(v), "Dedupe(%v)", v)
assert.ElementsMatchf(t, tt.want, DedupeSlice(v), "Dedupe(%v)", v)
case []int:
assert.Equalf(t, tt.want, DedupeSlice(v), "Dedupe(%v)", v)
assert.ElementsMatchf(t, tt.want, DedupeSlice(v), "Dedupe(%v)", v)
default:
t.Errorf("Unsupported slice type in test case: %v", tt.name)
}
})
}
}

func Test_EqualElements(t *testing.T) {
tests := []struct {
name string
x interface{}
y interface{}
want bool
}{
{
name: "string_slice_identical_elements",
x: []string{"a", "b", "c"},
y: []string{"a", "b", "c"},
want: true,
},
{
name: "string_slice_different_order",
x: []string{"a", "b", "c"},
y: []string{"c", "b", "a"},
want: true,
},
{
name: "string_slice_different_elements",
x: []string{"a", "b", "c"},
y: []string{"a", "b", "d"},
want: false,
},
{
name: "string_slice_different_lengths",
x: []string{"a", "b", "c"},
y: []string{"a", "b"},
want: false,
},
{
name: "int_slice_identical_elements",
x: []int{1, 2, 3},
y: []int{1, 2, 3},
want: true,
},
{
name: "int_slice_different_order",
x: []int{1, 2, 3},
y: []int{3, 2, 1},
want: true,
},
{
name: "int_slice_different_elements",
x: []int{1, 2, 3},
y: []int{1, 2, 4},
want: false,
},
{
name: "int_slice_different_lengths",
x: []int{1, 2, 3},
y: []int{1, 2},
want: false,
},
{
name: "empty_slices",
x: []int{},
y: []int{},
want: true,
},
{
name: "one_empty_slice",
x: []int{},
y: []int{1},
want: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
switch v1 := tt.x.(type) {
case []string:
v2 := tt.y.([]string)
assert.Equalf(t, tt.want, EqualElements(v1, v2), "EqualElements(%v, %v)", v1, v2)
case []int:
v2 := tt.y.([]int)
assert.Equalf(t, tt.want, EqualElements(v1, v2), "EqualElements(%v, %v)", v1, v2)
default:
t.Errorf("Unsupported slice type in test case: %v", tt.name)
}
})
}
}

func Test_SimplifyHDRSlice(t *testing.T) {
tests := []struct {
name string
input []string
want []string
}{
{
name: "contains_HDR",
input: []string{"HDR10", "HDR10+", "HDR"},
want: []string{"HDR", "HDR", "HDR"},
},
{
name: "no_HDR",
input: []string{"SDR", "DV"},
want: []string{"SDR", "DV"},
},
{
name: "empty_slice",
input: []string{},
want: []string{},
},
{
name: "mixed_HDR_and_others",
input: []string{"HDR10", "DV", "SDR", "HDR10+"},
want: []string{"HDR", "DV", "SDR", "HDR"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, SimplifyHDRSlice(tt.input), "SimplifyHDRSlice(%v)", tt.input)
})
}
}

0 comments on commit 7a3aa64

Please sign in to comment.