Repository navigation
Expand file tree
/
Copy pathdistinct.go
More file actions
82 lines (71 loc) · 2.23 KB
/
Copy pathdistinct.go
File metadata and controls
82 lines (71 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package linq
// Distinct method returns distinct elements from a collection. The result is an
// unordered collection that contains no duplicate values.
//
// Elements of basic comparable kinds (integers, floats, complex numbers,
// strings, booleans) are tracked in a strongly-typed set with no boxing. All
// other element types are tracked by their boxed (interface) values, so for
// them this method panics if T is not a comparable type at runtime; DistinctBy
// with a comparable key selector is the fast path for such types.
func (q Query[T]) Distinct() Query[T] {
return Query[T]{
Iterate: func(yield func(T) bool) {
set := newSeenSet[T]()
q.Iterate(func(item T) bool {
if set.add(item) {
return yield(item)
}
return true
})
},
}
}
// Distinct method returns distinct elements from a collection. The result is an
// ordered collection that contains no duplicate values.
//
// NOTE: Distinct method on OrderedQuery type has better performance than
// Distinct method on Query type.
func (oq OrderedQuery[T]) Distinct() OrderedQuery[T] {
distinct := Query[T]{
Iterate: func(yield func(T) bool) {
equal := equalFor[T]()
var previous T
isFirst := true
oq.Iterate(func(item T) bool {
if isFirst || !equal(item, previous) {
previous = item
isFirst = false
return yield(item)
}
return true
})
},
}
return OrderedQuery[T]{
compares: oq.compares,
original: distinct,
Query: distinct,
}
}
// DistinctBy method returns distinct elements from a collection. This method
// executes selector function for each element to determine a value to compare.
// The result is an unordered collection that contains no duplicate values.
//
// DistinctBy is a generic method: the comparison key type TKey is inferred from
// the selector function and must be comparable. Elements are tracked in a
// strongly-typed set, so no boxing occurs.
func (q Query[T]) DistinctBy[TKey comparable](selector func(T) TKey) Query[T] {
return Query[T]{
Iterate: func(yield func(T) bool) {
set := make(map[TKey]struct{})
q.Iterate(func(item T) bool {
key := selector(item)
if _, seen := set[key]; !seen {
set[key] = struct{}{}
return yield(item)
}
return true
})
},
}
}