-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2024 Michael Li <alimy@gility.net>. All rights reserved. | ||
// Use of this source code is governed by Apache License 2.0 that | ||
// can be found in the LICENSE file. | ||
|
||
package slices | ||
|
||
import ( | ||
"hash/maphash" | ||
) | ||
|
||
// DistinctFn return distinc elements of S | ||
func DistinctFn[S ~[]E, E any](s S, key func(e E) string) (res S) { | ||
seed := maphash.MakeSeed() | ||
return DistinctFunc(s, func(e E) int { | ||
return int(maphash.String(seed, key(e))) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2024 Michael Li <alimy@gility.net>. All rights reserved. | ||
// Use of this source code is governed by Apache License 2.0 that | ||
// can be found in the LICENSE file. | ||
|
||
package slices | ||
|
||
import ( | ||
"github.com/RoaringBitmap/roaring" | ||
) | ||
|
||
type keyable interface { | ||
Key() int | ||
} | ||
|
||
// Distinct return distinc elements of S | ||
func Distinct[S ~[]E, E keyable](s S) S { | ||
return DistinctFunc(s, func(e E) int { | ||
return e.Key() | ||
}) | ||
} | ||
|
||
// DistinctFunc return distinc elements of S | ||
func DistinctFunc[S ~[]E, E any](s S, key func(e E) int) (res S) { | ||
res = make(S, 0, len(s)) | ||
x, bitmap := 0, roaring.New() | ||
for _, e := range s { | ||
x = key(e) | ||
if !bitmap.ContainsInt(x) { | ||
res = append(res, e) | ||
bitmap.AddInt(x) | ||
} | ||
} | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Copyright 2024 Michael Li <alimy@gility.net>. All rights reserved. | ||
// Use of this source code is governed by Apache License 2.0 that | ||
// can be found in the LICENSE file. | ||
|
||
package slices_test | ||
|
||
import ( | ||
"cmp" | ||
stdSlices "slices" | ||
"testing" | ||
|
||
"github.com/alimy/tryst/slices" | ||
) | ||
|
||
type aliasInt int | ||
|
||
func (e aliasInt) Key() int { | ||
return int(e) | ||
} | ||
|
||
func TestDistinct(t *testing.T) { | ||
for _, d := range []struct { | ||
input []aliasInt | ||
expect []aliasInt | ||
}{ | ||
{ | ||
input: []aliasInt{1, 2, 3, 1, 2, 3, 4, 5, 2, 6}, | ||
expect: []aliasInt{1, 2, 3, 4, 5, 6}, | ||
}, | ||
{ | ||
input: []aliasInt{0, 2, 3, 1, 2, 3, 4, 5, 2, 6, 1, 1, 3, 5, 6, 0, 1, 2, 3}, | ||
expect: []aliasInt{0, 1, 2, 3, 4, 5, 6}, | ||
}, | ||
} { | ||
res := slices.Distinct(d.input) | ||
if !eqAliasIntSlice(res, d.expect) { | ||
t.Errorf("input:%v want:%v but got:%v", d.input, d.expect, res) | ||
} | ||
} | ||
} | ||
|
||
func TestDistinctFunc(t *testing.T) { | ||
for _, d := range []struct { | ||
input []int | ||
expect []int | ||
}{ | ||
{ | ||
input: []int{1, 2, 3, 1, 2, 3, 4, 5, 2, 6}, | ||
expect: []int{1, 2, 3, 4, 5, 6}, | ||
}, | ||
{ | ||
input: []int{0, 2, 3, 1, 2, 3, 4, 5, 2, 6, 1, 1, 3, 5, 6, 0, 1, 2, 3}, | ||
expect: []int{0, 1, 2, 3, 4, 5, 6}, | ||
}, | ||
} { | ||
res := slices.DistinctFunc(d.input, func(e int) int { | ||
return e | ||
}) | ||
if !eqSlice(res, d.expect) { | ||
t.Errorf("input:%v want:%v but got:%v", d.input, d.expect, res) | ||
} | ||
} | ||
} | ||
|
||
func TestDistinctFn(t *testing.T) { | ||
for _, d := range []struct { | ||
input []string | ||
expect []string | ||
}{ | ||
{ | ||
input: []string{"1", "2", "3", "1", "2", "3", "4", "5", "2", "6"}, | ||
expect: []string{"1", "2", "3", "4", "5", "6"}, | ||
}, | ||
{ | ||
input: []string{"abc", "bcd", "ccd", "abc", "ccd", "bcd", "a", "a", "b", "c"}, | ||
expect: []string{"abc", "bcd", "ccd", "a", "b", "c"}, | ||
}, | ||
} { | ||
res := slices.DistinctFn(d.input, func(e string) string { | ||
return e | ||
}) | ||
if !eqSlice(res, d.expect) { | ||
t.Errorf("input:%v want:%v but got:%v", d.input, d.expect, res) | ||
} | ||
} | ||
} | ||
|
||
func eqSlice[E cmp.Ordered](s1, s2 []E) bool { | ||
if len(s1) != len(s2) { | ||
return false | ||
} | ||
stdSlices.Sort(s1) | ||
stdSlices.Sort(s2) | ||
for i := 0; i < len(s1); i++ { | ||
if s1[i] != s2[i] { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
func eqAliasIntSlice(s1, s2 []aliasInt) bool { | ||
t1, t2 := toIntSlice(s1), toIntSlice(s2) | ||
return eqSlice(t1, t2) | ||
} | ||
|
||
func toIntSlice(s []aliasInt) []int { | ||
res := make([]int, 0, len(s)) | ||
for _, e := range s { | ||
res = append(res, int(e)) | ||
} | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Copyright 2024 Michael Li <alimy@gility.net>. All rights reserved. | ||
// Use of this source code is governed by Apache License 2.0 that | ||
// can be found in the LICENSE file. | ||
|
||
package utils | ||
|
||
import "unsafe" | ||
|
||
// String convert bytes to string | ||
func String(data []byte) (res string) { | ||
if size := len(data); size > 0 { | ||
res = unsafe.String(unsafe.SliceData(data), size) | ||
} | ||
return | ||
} | ||
|
||
// Bytes convert string to []byte | ||
func Bytes(data string) (res []byte) { | ||
if size := len(data); size > 0 { | ||
res = unsafe.Slice(unsafe.StringData(data), size) | ||
} else { | ||
res = []byte{} | ||
} | ||
return | ||
} |