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

feat: add Distinct

This commit is contained in:
dudaodong
2023-01-17 11:39:05 +08:00
parent 61338b6b46
commit a3bc20af1d
2 changed files with 67 additions and 2 deletions

View File

@@ -6,7 +6,12 @@
// powerful like other libs
package stream
import "golang.org/x/exp/constraints"
import (
"bytes"
"encoding/gob"
"golang.org/x/exp/constraints"
)
// A stream should implements methods:
// type StreamI[T any] interface {
@@ -69,6 +74,34 @@ func FromRange[T constraints.Integer | constraints.Float](start, end, step T) st
return stream[T]{source: source}
}
// Distinct returns a stream that removes the duplicated items.
func (s stream[T]) Distinct() stream[T] {
source := make([]T, 0)
distinct := map[string]bool{}
for _, v := range s.source {
// todo: performance issue
k := hashKey(v)
if _, ok := distinct[k]; !ok {
distinct[k] = true
source = append(source, v)
}
}
return FromSlice(source)
}
func hashKey(data any) string {
buffer := bytes.NewBuffer(nil)
encoder := gob.NewEncoder(buffer)
err := encoder.Encode(data)
if err != nil {
panic("stream.hashKey: get hashkey failed")
}
return buffer.String()
}
// ToSlice return the elements in the stream.
func (s stream[T]) ToSlice() []T {
return s.source

View File

@@ -15,7 +15,7 @@ func TestFromSlice(t *testing.T) {
}
func TestFromRange(t *testing.T) {
assert := internal.NewAssert(t, "TestFromSlice")
assert := internal.NewAssert(t, "TestFromRange")
s1 := FromRange(1, 5, 1)
s2 := FromRange(1.1, 5.0, 1.0)
@@ -23,3 +23,35 @@ func TestFromRange(t *testing.T) {
assert.Equal([]int{1, 2, 3, 4, 5}, s1.ToSlice())
assert.Equal([]float64{1.1, 2.1, 3.1, 4.1}, s2.ToSlice())
}
func TestStream_Distinct(t *testing.T) {
assert := internal.NewAssert(t, "TestStream_Distinct")
nums := FromSlice([]int{1, 2, 2, 3, 3, 3})
distinctNums := nums.Distinct()
assert.Equal([]int{1, 2, 2, 3, 3, 3}, nums.ToSlice())
assert.Equal([]int{1, 2, 3}, distinctNums.ToSlice())
type Person struct {
Id string
Name string
Age uint
}
people := []Person{
{Id: "001", Name: "Tom", Age: 10},
{Id: "001", Name: "Tom", Age: 10},
{Id: "002", Name: "Jim", Age: 20},
{Id: "003", Name: "Mike", Age: 30},
}
stream := FromSlice(people)
distinctStream := stream.Distinct()
// {[{001 Tom 10} {001 Tom 10} {002 Jim 20} {003 Mike 30}]}
t.Log(stream)
// {[{001 Tom 10} {002 Jim 20} {003 Mike 30}]}
t.Log(distinctStream)
}