Skip to content

Commit a662462

Browse files
committed
Cannot properly compare equal to without equality comparison functions.
1 parent d2fb1f4 commit a662462

File tree

4 files changed

+27
-70
lines changed

4 files changed

+27
-70
lines changed

bounds.go

Lines changed: 12 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,12 @@ package sortedmap
33
import "sort"
44

55
func (sm *SortedMap) setBoundIdx(boundVal interface{}) int {
6-
76
if boundVal == nil {
87
return 0
98
}
10-
11-
smLen := len(sm.sorted)
12-
idx := sort.Search(smLen, func(i int) bool {
9+
return sort.Search(len(sm.sorted), func(i int) bool {
1310
return sm.lessFn(boundVal, sm.idx[sm.sorted[i]])
1411
})
15-
16-
// sort.Search returns the smallest index i in [0, n) at which f(i) is true.
17-
// This sets the correct index for less than conditional comparisons.
18-
if idx > 0 {
19-
idx--
20-
}
21-
22-
return idx
23-
}
24-
25-
func (sm *SortedMap) lowerBoundIncrCondition(i, j interface{}) bool {
26-
return sm.lessFn(j, i)
27-
}
28-
29-
func (sm *SortedMap) lowerBoundRetCondition(i, j interface{}) bool {
30-
return sm.lessFn(j, i)
31-
}
32-
33-
func (sm *SortedMap) upperBoundIncrCondition(i, j interface{}) bool {
34-
return !sm.lessFn(j, i) && !sm.lessFn(i, j)
35-
}
36-
37-
func (sm *SortedMap) upperBoundRetCondition(i, j interface{}) bool {
38-
return sm.lessFn(i, j)
39-
}
40-
41-
func (sm *SortedMap) adjustIdxOrReturn(boundVal interface{}, incrCondition, retCondition func(boundVal, valFromIdx interface{}) bool) (int, bool) {
42-
idx := sm.setBoundIdx(boundVal)
43-
if idx < len(sm.sorted)-1 {
44-
valFromIdx := sm.idx[sm.sorted[idx]]
45-
46-
if incrCondition(boundVal, valFromIdx) {
47-
idx++
48-
}
49-
50-
valFromIdx = sm.idx[sm.sorted[idx]]
51-
if retCondition(boundVal, valFromIdx) {
52-
return idx, false
53-
}
54-
}
55-
return idx, true
5612
}
5713

5814
func (sm *SortedMap) boundsIdxSearch(lowerBound, upperBound interface{}) []int {
@@ -68,22 +24,23 @@ func (sm *SortedMap) boundsIdxSearch(lowerBound, upperBound interface{}) []int {
6824
}
6925

7026
lowerBoundIdx := sm.setBoundIdx(lowerBound)
71-
if lowerBound != nil {
72-
var ok bool
73-
lowerBoundIdx, ok = sm.adjustIdxOrReturn(lowerBound, sm.lowerBoundIncrCondition, sm.lowerBoundRetCondition)
74-
if !ok {
75-
return nil
76-
}
27+
if lowerBoundIdx == smLen {
28+
lowerBoundIdx--
29+
}
30+
if lowerBoundIdx > 0 && sm.lessFn(sm.idx[sm.sorted[lowerBoundIdx]], lowerBound) {
31+
lowerBoundIdx++
7732
}
7833

7934
upperBoundIdx := 0
8035
if upperBound == nil {
8136
upperBoundIdx = smLen - 1
8237
} else {
83-
var ok bool
84-
upperBoundIdx, ok = sm.adjustIdxOrReturn(upperBound, sm.upperBoundIncrCondition, sm.upperBoundRetCondition)
85-
if !ok {
86-
return nil
38+
upperBoundIdx = sm.setBoundIdx(upperBound)
39+
if upperBoundIdx == smLen {
40+
upperBoundIdx--
41+
}
42+
if upperBoundIdx > 0 && sm.lessFn(upperBound, sm.idx[sm.sorted[upperBoundIdx]]) {
43+
upperBoundIdx--
8744
}
8845
}
8946

examples/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func main() {
147147

148148
### BoundedIterCh
149149

150-
```BoundedIterCh``` selects the records equal to or between the given bounds. Its first argument allows for reversing the order of the returned records.
150+
```BoundedIterCh``` selects values that are greater than the lower bound and are less than or equal to the upper bound. Its first argument allows for reversing the order of the returned records.
151151

152152
```go
153153
package main
@@ -373,7 +373,7 @@ func main() {
373373

374374
### BoundedDelete
375375

376-
```BoundedDelete``` is a similar pattern as the above ```Bounded``` methods. ```BoundedDelete``` removes values that are equal to or between the provided bounds values.
376+
```BoundedDelete``` is a similar pattern as the above ```Bounded``` methods. ```BoundedDelete``` removes values that are greater than the lower bound and lower than or equal to the upper bound.
377377

378378
```go
379379
package main

sortedmap.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package sortedmap
22

3-
// SortedMap contains a map, a slice, and a reference to a sorting function.
3+
// SortedMap contains a map, a slice, and references to one or more comparison functions.
44
// SortedMap is not concurrency-safe, though it can be easily wrapped by a developer-defined type.
55
type SortedMap struct {
66
idx map[interface{}]interface{}
77
sorted []interface{}
8-
lessFn SortLessFunc
8+
lessFn ComparisonFunc
99
}
1010

1111
// Record defines a type used in batching and iterations, where keys and values are used together.
@@ -14,27 +14,27 @@ type Record struct {
1414
Val interface{}
1515
}
1616

17-
// SortLessFunc defines the type of the comparison function for the chosen value type.
18-
type SortLessFunc func(i, j interface{}) bool
17+
// ComparisonFunc defines the type of the comparison function for the chosen value type.
18+
type ComparisonFunc func(i, j interface{}) bool
1919

20-
func unsortedSortLessFunc(_, _ interface{}) bool {
20+
func noOpComparisonFunc(_, _ interface{}) bool {
2121
return false
2222
}
2323

24-
func setLessFunc(lessFn SortLessFunc) SortLessFunc {
25-
if lessFn == nil {
26-
return unsortedSortLessFunc
24+
func setComparisonFunc(cmpFn ComparisonFunc) ComparisonFunc {
25+
if cmpFn == nil {
26+
return noOpComparisonFunc
2727
}
28-
return lessFn
28+
return cmpFn
2929
}
3030

3131
// New creates and initializes a new SortedMap structure and then returns a reference to it.
3232
// New SortedMaps are created with a backing map/slice of length/capacity n.
33-
func New(n int, lessFn SortLessFunc) *SortedMap {
33+
func New(n int, cmpFn ComparisonFunc) *SortedMap {
3434
return &SortedMap{
3535
idx: make(map[interface{}]interface{}, n),
3636
sorted: make([]interface{}, 0, n),
37-
lessFn: setLessFunc(lessFn),
37+
lessFn: setComparisonFunc(cmpFn),
3838
}
3939
}
4040

sortedmap_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ func TestNew(t *testing.T) {
2323
}
2424
}
2525

26-
func TestUnsortedLessFunc(t *testing.T) {
26+
func TestNoOpFuncs(t *testing.T) {
2727
if New(0, nil).lessFn(nil, nil) {
28-
t.Fatal("TestUnsortedLessFunc failed: lessFn returned true!")
28+
t.Fatal("TestNoOpFuncs failed: lessFn returned true!")
2929
}
3030
}
3131

0 commit comments

Comments
 (0)