1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

feat: add UniqueByParallel for slice

This commit is contained in:
dudaodong
2024-08-08 10:20:52 +08:00
parent 9be124211e
commit 356351896d
3 changed files with 122 additions and 0 deletions

View File

@@ -1163,3 +1163,15 @@ func ExampleLeftPadding() {
// Output: // Output:
// [0 0 0 1 2 3 4 5] // [0 0 0 1 2 3 4 5]
} }
func ExampleUniqueByParallel() {
nums := []int{1, 2, 3, 1, 2, 4, 5, 6, 4, 7}
numOfThreads := 4
comparator := func(item int, other int) bool { return item == other }
result := UniqueByParallel(nums, numOfThreads, comparator)
fmt.Println(result)
// Output:
// [1 2 3 4 5 6 7]
}

96
slice/slice_parallel.go Normal file
View File

@@ -0,0 +1,96 @@
// Copyright 2024 dudaodong@gmail.com. All rights resulterved.
// Use of this source code is governed by MIT license
package slice
import (
"runtime"
"sync"
)
// UniqueByParallel removes duplicate elements from the slice by parallel
// The comparator function is used to compare the elements
// The numOfThreads parameter specifies the number of threads to use
// If numOfThreads is less than or equal to 0, it will be set to 1
// The comparator function should return true if the two elements are equal
// Play: todo
func UniqueByParallel[T comparable](slice []T, numOfThreads int, comparator func(item T, other T) bool) []T {
if numOfThreads <= 0 {
numOfThreads = 1
} else if numOfThreads > len(slice) {
numOfThreads = len(slice)
}
maxThreads := runtime.NumCPU()
if numOfThreads > maxThreads {
numOfThreads = maxThreads
}
removeDuplicate := func(items []T, comparator func(item T, other T) bool) []T {
var result []T
for _, item := range items {
seen := false
for _, r := range result {
if comparator(item, r) {
seen = true
break
}
}
if !seen {
result = append(result, item)
}
}
return result
}
chunkSize := (len(slice) + numOfThreads - 1) / numOfThreads
chunks := make([][]T, 0, numOfThreads)
for i := 0; i < len(slice); i += chunkSize {
end := i + chunkSize
if end > len(slice) {
end = len(slice)
}
chunks = append(chunks, slice[i:end])
}
type resultChunk struct {
index int
data []T
}
resultCh := make(chan resultChunk, numOfThreads)
var wg sync.WaitGroup
for i, chunk := range chunks {
wg.Add(1)
go func(index int, chunk []T) {
defer wg.Done()
resultCh <- resultChunk{index, removeDuplicate(chunk, comparator)}
}(i, chunk)
}
go func() {
wg.Wait()
close(resultCh)
}()
results := make([][]T, len(chunks))
for r := range resultCh {
results[r.index] = r.data
}
result := []T{}
seen := make(map[T]bool)
for _, chunk := range results {
for _, item := range chunk {
if !seen[item] {
seen[item] = true
result = append(result, item)
}
}
}
return result
}

View File

@@ -1448,3 +1448,17 @@ func TestRightPaddingAndLeftPadding(t *testing.T) {
padded := LeftPadding(RightPadding(nums, 0, 3), 0, 3) padded := LeftPadding(RightPadding(nums, 0, 3), 0, 3)
assert.Equal([]int{0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0}, padded) assert.Equal([]int{0, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0}, padded)
} }
func TestUniqueByParallel(t *testing.T) {
t.Parallel()
assert := internal.NewAssert(t, "TestUniqueByParallel")
nums := []int{1, 2, 3, 1, 2, 4, 5, 6, 4, 7}
numOfThreads := 4
comparator := func(item int, other int) bool { return item == other }
result := UniqueByParallel(nums, numOfThreads, comparator)
assert.Equal([]int{1, 2, 3, 4, 5, 6, 7}, result)
}