Skip to content

Commit f3141d6

Browse files
committed
Optimize fieldpath.Set#Leaves
1 parent a90e678 commit f3141d6

File tree

2 files changed

+57
-22
lines changed

2 files changed

+57
-22
lines changed

fieldpath/set.go

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -206,30 +206,32 @@ func (s *Set) WithPrefix(pe PathElement) *Set {
206206
return subset
207207
}
208208

209+
func (s *Set) leavesPrefix(prefix Path, set *Set) {
210+
for _, child := range s.Children.members {
211+
child.set.leavesPrefix(append(prefix, child.pathElement), set)
212+
}
213+
214+
for _, mem := range s.Members.members {
215+
isChild := false
216+
currentPath := append(prefix, mem)
217+
for _, child := range s.Children.members {
218+
if mem.Equals(child.pathElement) {
219+
isChild = true
220+
}
221+
}
222+
if !isChild {
223+
// any members that are not also children are leaves
224+
set.Insert(currentPath)
225+
}
226+
}
227+
}
228+
209229
// Leaves returns a set containing only the leaf paths
210230
// of a set.
211231
func (s *Set) Leaves() *Set {
212-
paths := []Path{}
213-
s.Iterate(func(p Path) {
214-
parentPath := Path(p[0 : len(p)-1])
215-
n := 0
216-
for _, path := range paths {
217-
// perform preorder DFS on every path in the set,
218-
// if the parent of the current path exists in paths
219-
// then the parent must not be a leaf and should be
220-
// overwritten by the current path
221-
if !parentPath.Equals(path) {
222-
paths[n] = path
223-
n++
224-
}
225-
}
226-
paths = paths[:n]
227-
// save a copy of current path or else it can be overwritten
228-
pathCopy := Path(make([]PathElement, len(p)))
229-
copy(pathCopy, p)
230-
paths = append(paths, pathCopy)
231-
})
232-
return NewSet(paths...)
232+
out := &Set{}
233+
s.leavesPrefix(Path{}, out)
234+
return out
233235
}
234236

235237
// setNode is a pair of PathElement / Set, for the purpose of expressing

fieldpath/set_test.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,23 +496,56 @@ func TestSetLeaves(t *testing.T) {
496496
_P("root", "l1", "l2", "l3"),
497497
),
498498
}, {
499-
name: "nested with lists",
499+
name: "multiple values, check for overwrite",
500+
input: NewSet(
501+
_P("root", KeyByFields("name", "a")),
502+
_P("root", KeyByFields("name", "a"), "name"),
503+
_P("root", KeyByFields("name", "a"), "value", "b"),
504+
_P("root", KeyByFields("name", "a"), "value", "c"),
505+
),
506+
expected: NewSet(
507+
_P("root", KeyByFields("name", "a"), "name"),
508+
_P("root", KeyByFields("name", "a"), "value", "b"),
509+
_P("root", KeyByFields("name", "a"), "value", "c"),
510+
),
511+
}, {
512+
name: "multiple values and nested",
513+
input: NewSet(
514+
_P("root", KeyByFields("name", "a")),
515+
_P("root", KeyByFields("name", "a"), "name"),
516+
_P("root", KeyByFields("name", "a"), "value", "b"),
517+
_P("root", KeyByFields("name", "a"), "value", "b", "d"),
518+
_P("root", KeyByFields("name", "a"), "value", "c"),
519+
),
520+
expected: NewSet(
521+
_P("root", KeyByFields("name", "a"), "name"),
522+
_P("root", KeyByFields("name", "a"), "value", "b", "d"),
523+
_P("root", KeyByFields("name", "a"), "value", "c"),
524+
),
525+
}, {
526+
name: "all-in-one",
500527
input: NewSet(
501528
_P("root"),
502529
_P("root", KeyByFields("name", "a")),
503530
_P("root", KeyByFields("name", "a"), "name"),
504531
_P("root", KeyByFields("name", "a"), "value", "b"),
505532
_P("root", KeyByFields("name", "a"), "value", "b", "c"),
533+
_P("root", KeyByFields("name", "a"), "value", "d"),
534+
_P("root", KeyByFields("name", "a"), "value", "e"),
506535
_P("root", "x"),
507536
_P("root", "x", "y"),
537+
_P("root", "x", "z"),
508538
_P("root", KeyByFields("name", "p")),
509539
_P("root", KeyByFields("name", "p"), "name"),
510540
_P("root", KeyByFields("name", "p"), "value", "q"),
511541
),
512542
expected: NewSet(
513543
_P("root", KeyByFields("name", "a"), "name"),
514544
_P("root", KeyByFields("name", "a"), "value", "b", "c"),
545+
_P("root", KeyByFields("name", "a"), "value", "d"),
546+
_P("root", KeyByFields("name", "a"), "value", "e"),
515547
_P("root", "x", "y"),
548+
_P("root", "x", "z"),
516549
_P("root", KeyByFields("name", "p"), "name"),
517550
_P("root", KeyByFields("name", "p"), "value", "q"),
518551
),

0 commit comments

Comments
 (0)