diff --git a/bench_filter_test.go b/bench_filter_test.go index 38e39f5..44e5917 100644 --- a/bench_filter_test.go +++ b/bench_filter_test.go @@ -2,6 +2,8 @@ package goquery import ( "testing" + + "github.com/andybalholm/cascadia" ) func BenchmarkFilter(b *testing.B) { @@ -40,6 +42,25 @@ func BenchmarkNot(b *testing.B) { } } +func BenchmarkNotMatcher(b *testing.B) { + var n int + + b.StopTimer() + sel := DocW().Find("li") + m := cascadia.MustCompile(".toclevel-2") + b.StartTimer() + for i := 0; i < b.N; i++ { + if n == 0 { + n = sel.NotMatcher(m).Length() + } else { + sel.NotMatcher(m) + } + } + if n != 371 { + b.Fatalf("want 371, got %d", n) + } +} + func BenchmarkFilterFunction(b *testing.B) { var n int diff --git a/filter.go b/filter.go index 9138ffb..271f050 100644 --- a/filter.go +++ b/filter.go @@ -130,10 +130,14 @@ func winnow(sel *Selection, m Matcher, keep bool) []*html.Node { if keep { return m.Filter(sel.Nodes) } - // Use grep - return grep(sel, func(i int, s *Selection) bool { - return !m.Match(s.Get(0)) - }) + // Not path: call Match directly on each node, no Selection wrapper needed + result := make([]*html.Node, 0, len(sel.Nodes)) + for _, n := range sel.Nodes { + if !m.Match(n) { + result = append(result, n) + } + } + return result } // Filter based on an array of nodes, and the indicator to keep (Filter) or