-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Trie.Walk() and Node.SetValue() (#4)
* udpate: add support for SelectOnValue, find item in the tree based on Value, using eval function * update: renaming, cleaning tests * update: renaming, SelectOnValue -> Walk, implement with childrenDLL to avoid non deterministic sort. * Add support for Trie.Walk() and Node.SetValue() * Fix err on Windows + Fix docs --------- Co-authored-by: tophe <cvigny@artprice.com> Co-authored-by: Shivam Mamgain <smamgain@microsoft.com>
- Loading branch information
1 parent
23eb4c7
commit fdf2c27
Showing
6 changed files
with
142 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package trie | ||
|
||
type WalkFunc func(key []string, node *Node) error | ||
|
||
// Walk traverses the Trie and calls walker function. If walker function returns an error, Walk early-returns with that error. | ||
// Traversal follows insertion order. | ||
func (t *Trie) Walk(key []string, walker WalkFunc) error { | ||
node := t.root | ||
for _, keyPart := range key { | ||
child, ok := node.children[keyPart] | ||
if !ok { | ||
return nil | ||
} | ||
node = child | ||
} | ||
return t.walk(node, &key, walker) | ||
} | ||
|
||
func (t *Trie) walk(node *Node, prefixKey *[]string, walker WalkFunc) error { | ||
if node.isTerminal { | ||
key := make([]string, len(*prefixKey)) | ||
copy(key, *prefixKey) | ||
if err := walker(key, node); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
for dllNode := node.childrenDLL.head; dllNode != nil; dllNode = dllNode.next { | ||
child := dllNode.trieNode | ||
*prefixKey = append(*prefixKey, child.keyPart) | ||
err := t.walk(child, prefixKey, walker) | ||
*prefixKey = (*prefixKey)[:len(*prefixKey)-1] | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package trie_test | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
|
||
"github.com/shivamMg/trie" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestTrie_WalkErr(t *testing.T) { | ||
tri := trie.New() | ||
tri.Put([]string{"d", "a", "l", "i"}, 1) | ||
tri.Put([]string{"d", "a", "l", "i", "b"}, 2) | ||
tri.Put([]string{"d", "a", "l", "i", "b", "e"}, 3) | ||
tri.Put([]string{"d", "a", "l", "i", "b", "e", "r", "t"}, 4) | ||
|
||
var selected []string | ||
walker := func(key []string, node *trie.Node) error { | ||
what := node.Value().(int) | ||
if what == 3 { | ||
selected = key | ||
return errors.New("found") | ||
} | ||
return nil | ||
} | ||
|
||
err := tri.Walk(nil, walker) | ||
assert.EqualError(t, err, "found") | ||
assert.EqualValues(t, []string{"d", "a", "l", "i", "b", "e"}, selected) | ||
} | ||
|
||
func TestTrie_Walk(t *testing.T) { | ||
tri := trie.New() | ||
tri.Put([]string{"d", "a", "l", "i"}, []int{0, 1, 2, 4, 5}) | ||
tri.Put([]string{"d", "a", "l", "i", "b"}, []int{1, 2, 4, 5}) | ||
tri.Put([]string{"d", "a", "l", "i", "b", "e"}, []int{1, 0, 2, 4, 5, 0}) | ||
tri.Put([]string{"d", "a", "l", "i", "b", "e", "r", "t"}, []int{1, 2, 4, 5}) | ||
type KVPair struct { | ||
key []string | ||
value []int | ||
} | ||
var selected []KVPair | ||
walker := func(key []string, node *trie.Node) error { | ||
what := node.Value().([]int) | ||
for _, i := range what { | ||
if i == 0 { | ||
selected = append(selected, KVPair{key, what}) | ||
break | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
err := tri.Walk(nil, walker) | ||
assert.NoError(t, err) | ||
expected := []KVPair{ | ||
{[]string{"d", "a", "l", "i"}, []int{0, 1, 2, 4, 5}}, | ||
{[]string{"d", "a", "l", "i", "b", "e"}, []int{1, 0, 2, 4, 5, 0}}, | ||
} | ||
assert.EqualValues(t, expected, selected) | ||
|
||
selected = nil | ||
err = tri.Walk([]string{"d", "a", "l", "i", "b"}, walker) | ||
assert.NoError(t, err) | ||
expected = []KVPair{ | ||
{[]string{"d", "a", "l", "i", "b", "e"}, []int{1, 0, 2, 4, 5, 0}}, | ||
} | ||
assert.EqualValues(t, expected, selected) | ||
|
||
selected = nil | ||
err = tri.Walk([]string{"a", "b", "c"}, walker) | ||
assert.NoError(t, err) | ||
assert.Nil(t, selected) | ||
} |