From 846e01166bc951b11be089c03d77879b1294265e Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Fri, 22 Dec 2023 13:36:29 -0800 Subject: [PATCH] Flatten fltr funcs into used methods --- attribute/set.go | 107 +++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 59 deletions(-) diff --git a/attribute/set.go b/attribute/set.go index 4734d4103a7..dd4a55e60e0 100644 --- a/attribute/set.go +++ b/attribute/set.go @@ -249,7 +249,7 @@ func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) { // // The second []KeyValue return value is a list of attributes that were // excluded by the Filter (if non-nil). -func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (Set, []KeyValue) { +func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, keep Filter) (Set, []KeyValue) { // Check for empty set. if len(kvs) == 0 { return empty(), nil @@ -263,72 +263,55 @@ func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (S *tmp = nil - // Use filteredToFront here for last-value-wins semantics. - uniq := filteredToFront(kvs, func() func(kv KeyValue) bool { - firstCall := true - var prev Key - return func(kv KeyValue) bool { - if firstCall { - firstCall, prev = false, kv.Key - } else { - if kv.Key == prev { - return false - } - prev = kv.Key - } - return true - } - }()) - kvs = kvs[uniq:] - - if filter != nil { - // Unique prior to filtering so the returned dropped attributes will - // not also include the deduplicated attributes. - k := filteredToBack(kvs, filter) - if k == len(kvs) { - return Set{equivalent: computeDistinct(kvs[:k])}, nil - } - return Set{equivalent: computeDistinct(kvs[:k])}, kvs[k:] + if keep == nil { + keep = func(KeyValue) bool { return true } } - return Set{equivalent: computeDistinct(kvs)}, nil -} + n := len(kvs) + prev := kvs[n-1] -// filteredToBack filters slice in-place using f. All KeyValues that need to be -// removed are moved to the end. All KeyValues that need to be kept are moved -// (in-order) to the front. The index for the first KeyValue to be removed is -// returned. -func filteredToBack(slice []KeyValue, keep Filter) int { - var j int - for i := 0; i < len(slice); i++ { - if keep(slice[i]) { - slice[i], slice[j] = slice[j], slice[i] - j++ - } + kept := n // Starting index of kept KeyValues. + if keep(prev) { + kept-- } - return j -} -// filteredToFront filters slice in-place using f. All KeyValues that need to -// be removed are moved to the front. All KeyValues that need to be kept are -// moved (in-order) to the back. The index for the first KeyValue to be kept is -// returned. -func filteredToFront(slice []KeyValue, keep Filter) int { - n := len(slice) - j := n - for i := n - 1; i >= 0; i-- { - if keep(slice[i]) { - j-- - slice[i], slice[j] = slice[j], slice[i] + // Instead of iterating kvs once to de-duplicate and another time to + // filter, do both in a single pass. + // + // Iterate from back-to-front for last-value-wins semantics. + for i := n - 2; i >= 0; i-- { + kv := kvs[i] + if kv.Key == prev.Key { + // Delete duplicate from kvs while preserving order and keeping + // the deleted KeyValue in original slice. + copy(kvs[i:], kvs[i+1:]) + kvs[len(kvs)-1] = kv + kvs = kvs[:len(kvs)-1] + + // Update kept index for new kvs size. + kept-- + } else { + prev = kv + if keep(kv) { + kept-- + kvs[i], kvs[kept] = kvs[kept], kvs[i] + } } } - return j + + switch kept { + case 0: + return Set{equivalent: computeDistinct(kvs)}, nil + case n: + return empty(), kvs + } + return Set{equivalent: computeDistinct(kvs[kept:])}, kvs[:kept] } // Filter returns a filtered copy of this Set. See the documentation for // NewSetWithSortableFiltered for more details. -func (l *Set) Filter(re Filter) (Set, []KeyValue) { - if re == nil { +func (l *Set) Filter(keep Filter) (Set, []KeyValue) { + if keep == nil { return *l, nil } @@ -336,7 +319,7 @@ func (l *Set) Filter(re Filter) (Set, []KeyValue) { start, n := 0, l.Len() for ; start < n; start++ { kv, _ := l.Get(start) - if !re(kv) { + if !keep(kv) { break } } @@ -352,7 +335,7 @@ func (l *Set) Filter(re Filter) (Set, []KeyValue) { // immutable and filtering should not change this. slice := l.ToSlice() - // Do not re-evaluate re(slice[i]). + // Do not re-evaluate keep(slice[i]). end := len(slice) - 1 if start == end { return Set{equivalent: computeDistinct(slice[:start])}, slice[start:] @@ -362,7 +345,13 @@ func (l *Set) Filter(re Filter) (Set, []KeyValue) { copy(slice[start:], slice[start+1:]) slice[end] = kv - div := filteredToBack(slice[start:end], re) + start + div := start // Index of the first KeyValue to be removed. + for i := start; i < end; i++ { + if keep(slice[i]) { + slice[i], slice[div] = slice[div], slice[i] + div++ + } + } return Set{equivalent: computeDistinct(slice[:div])}, slice[div:] }