mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-18 21:35:24 +01:00
fn: add Filter to List
This commit adds an immutable Filter method to the linked List API. This is useful because there are several instances wherein we iterate through the linked List and only process a subset of it in some way or another.
This commit is contained in:
parent
779903af9d
commit
f7264e6a5b
15
fn/list.go
15
fn/list.go
@ -300,3 +300,18 @@ func (l *List[A]) PushFrontList(other *List[A]) {
|
|||||||
n = n.Prev()
|
n = n.Prev()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter gives a slice of all of the node values that satisfy the given
|
||||||
|
// predicate.
|
||||||
|
func (l *List[A]) Filter(f Pred[A]) []A {
|
||||||
|
var acc []A
|
||||||
|
|
||||||
|
for cursor := l.Front(); cursor != nil; cursor = cursor.Next() {
|
||||||
|
a := cursor.Value
|
||||||
|
if f(a) {
|
||||||
|
acc = append(acc, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
@ -5,6 +5,9 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/quick"
|
"testing/quick"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenList(r *rand.Rand) *List[uint32] {
|
func GenList(r *rand.Rand) *List[uint32] {
|
||||||
@ -727,3 +730,93 @@ func TestMoveUnknownMark(t *testing.T) {
|
|||||||
checkList(t, &l1, []int{1})
|
checkList(t, &l1, []int{1})
|
||||||
checkList(t, &l2, []int{2})
|
checkList(t, &l2, []int{2})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFilterIdempotence ensures that the slice coming out of List.Filter is
|
||||||
|
// the same as that slice filtered again by the same predicate.
|
||||||
|
func TestFilterIdempotence(t *testing.T) {
|
||||||
|
require.NoError(
|
||||||
|
t, quick.Check(
|
||||||
|
func(l *List[uint32], modSize uint32) bool {
|
||||||
|
pred := func(a uint32) bool {
|
||||||
|
return a%modSize != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered := l.Filter(pred)
|
||||||
|
|
||||||
|
filteredAgain := Filter(pred, filtered)
|
||||||
|
|
||||||
|
return slices.Equal(filtered, filteredAgain)
|
||||||
|
},
|
||||||
|
&quick.Config{
|
||||||
|
Values: func(vs []reflect.Value, r *rand.Rand) {
|
||||||
|
l := GenList(r)
|
||||||
|
vs[0] = reflect.ValueOf(l)
|
||||||
|
vs[1] = reflect.ValueOf(
|
||||||
|
r.Uint32()%5 + 1,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestFilterShrinks ensures that the length of the slice returned from
|
||||||
|
// List.Filter is never larger than the length of the List.
|
||||||
|
func TestFilterShrinks(t *testing.T) {
|
||||||
|
require.NoError(
|
||||||
|
t, quick.Check(
|
||||||
|
func(l *List[uint32], modSize uint32) bool {
|
||||||
|
pred := func(a uint32) bool {
|
||||||
|
return a%modSize != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredSize := len(l.Filter(pred))
|
||||||
|
|
||||||
|
return filteredSize <= l.Len()
|
||||||
|
},
|
||||||
|
&quick.Config{
|
||||||
|
Values: func(vs []reflect.Value, r *rand.Rand) {
|
||||||
|
l := GenList(r)
|
||||||
|
vs[0] = reflect.ValueOf(l)
|
||||||
|
vs[1] = reflect.ValueOf(
|
||||||
|
r.Uint32()%5 + 1,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestFilterLawOfExcludedMiddle ensures that if we intersect a List.Filter
|
||||||
|
// with its negation that the intersection is the empty set.
|
||||||
|
func TestFilterLawOfExcludedMiddle(t *testing.T) {
|
||||||
|
require.NoError(
|
||||||
|
t, quick.Check(
|
||||||
|
func(l *List[uint32], modSize uint32) bool {
|
||||||
|
pred := func(a uint32) bool {
|
||||||
|
return a%modSize != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
negatedPred := func(a uint32) bool {
|
||||||
|
return !pred(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
positive := NewSet(l.Filter(pred)...)
|
||||||
|
negative := NewSet(l.Filter(negatedPred)...)
|
||||||
|
|
||||||
|
return positive.Intersect(negative).Equal(
|
||||||
|
NewSet[uint32](),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
&quick.Config{
|
||||||
|
Values: func(vs []reflect.Value, r *rand.Rand) {
|
||||||
|
l := GenList(r)
|
||||||
|
vs[0] = reflect.ValueOf(l)
|
||||||
|
vs[1] = reflect.ValueOf(
|
||||||
|
r.Uint32()%5 + 1,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user