Skip to content

Commit

Permalink
Merge pull request #16 from ikawaha/fix/interface_common_prefix_search
Browse files Browse the repository at this point in the history
Modify the interface of the common prefix search
  • Loading branch information
ikawaha authored Dec 16, 2018
2 parents 320eeb6 + dc616f6 commit 3201d12
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 59 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ func main() {
if err != nil {
panic(err)
}
ids, sizes, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
for i := 0; i < len(ids); i++ {
fmt.Printf("id=%d, common prefix=%s\n", ids[i], "電気通信大学大学院大学"[0:sizes[i]])
ret, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
for i := 0; i < len(ret); i++ {
fmt.Printf("id=%d, common prefix=%s\n", ret[i][0], "電気通信大学大学院大学"[0:ret[i][1]])
}
}
```
Expand Down Expand Up @@ -101,9 +101,9 @@ func main() {
}
defer trie.Close() // ← ★
ids, sizes, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
ret, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
for i := 0; i < len(ids); i++ {
fmt.Printf("id=%d, common prefix=%s\n", ids[i], "電気通信大学大学院大学"[0:sizes[i]])
fmt.Printf("id=%d, common prefix=%s\n", ret[i][0], "電気通信大学大学院大学"[0:ret[i][1]])
}
}
```
Expand Down
8 changes: 4 additions & 4 deletions builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,15 @@ func TestBuildTRIE(t *testing.T) {
t.Errorf("unexpected error, %v", err)
}
t.Run("check", func(t *testing.T) {
ids, sizes, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
ret, err := trie.CommonPrefixSearch("電気通信大学大学院大学", 0)
if err != nil {
t.Errorf("unexpected error, %v", err)
}
for i := 0; i < len(ids); i++ {
if got, expected := ids[i], i; got != expected {
for i := 0; i < len(ret); i++ {
if got, expected := ret[i][0], i; got != expected {
t.Errorf("got %v, expected %v", got, expected)
}
if got, expected := "電気通信大学大学院大学"[0:sizes[i]], keys[i]; got != expected {
if got, expected := "電気通信大学大学院大学"[0:ret[i][1]], keys[i]; got != expected {
t.Errorf("got %v, expected %v", got, expected)
}
}
Expand Down
16 changes: 8 additions & 8 deletions internal/double_array_mmap_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,21 @@ func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error
return int(unit.value()), len(key), nil
}

// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the ids and it's lengths if found.
func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) (ids, sizes []int, err error) {
// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the array of pairs (id and it's length) if found.
func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) ([][2]int, error) {
var ret [][2]int
nodePos := uint32(0)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
nodePos ^= unit.offset()
for i := offset; i < len(key); i++ {
k := key[i]
nodePos ^= uint32(k)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
if unit.label() != k {
break
Expand All @@ -138,13 +139,12 @@ func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) (ids, size
if unit.hasLeaf() {
u, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
ids = append(ids, int(u.value()))
sizes = append(sizes, i+1)
ret = append(ret, [2]int{int(u.value()), i + 1})
}
}
return ids, sizes, nil
return ret, nil
}

// CommonPrefixSearchCallback finds keywords sharing common prefix in an input and callback with id and it's length.
Expand Down
39 changes: 25 additions & 14 deletions internal/double_array_mmap_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,13 @@ func TestMmapedDoubleArray_ExactMatchSearch(t *testing.T) {
ids[i] = uint32(i * 7)
}
builder := DoubleArrayBuilder{}
builder.Build(keys, ids)
if err := builder.Build(keys, ids); err != nil {
t.Fatalf("unexpected error, %v", err)
}
var b bytes.Buffer
builder.WriteTo(&b)
if _, err := builder.WriteTo(&b); err != nil {
t.Fatalf("unexpected error, %v", err)
}
mmaped := MmapedDoubleArray{raw: b.Bytes()}
for i, v := range keys {
id, size, err := mmaped.ExactMatchSearch(v)
Expand All @@ -86,19 +90,20 @@ func TestMmapedDoubleArray_CommonPrefixSearch(t *testing.T) {
}
t.Run("keys", func(t *testing.T) {
builder := DoubleArrayBuilder{}
builder.Build(keys, nil)
if err := builder.Build(keys, nil); err != nil {
t.Fatalf("unexpected error, %v", err)
}
var b bytes.Buffer
builder.WriteTo(&b)
if _, err := builder.WriteTo(&b); err != nil {
t.Fatalf("unexpected error, %v", err)
}
mmaped := MmapedDoubleArray{raw: b.Bytes()}
ids, sizes, err := mmaped.CommonPrefixSearch("電気通信大学大学院大学", 0)
ret, err := mmaped.CommonPrefixSearch("電気通信大学大学院大学", 0)
if err != nil {
t.Errorf("unexpected error, %v", err)
}
if expected := []int{2, 3, 4, 5, 6}; !reflect.DeepEqual(expected, ids) {
t.Errorf("ids: expected %v, got %v", expected, ids)
}
if expected := []int{6, 12, 18, 27, 33}; !reflect.DeepEqual(expected, sizes) {
t.Errorf("sizes: expected %v, got %v", expected, sizes)
if expected := [][2]int{[2]int{2, 6}, [2]int{3, 12}, [2]int{4, 18}, [2]int{5, 27}, [2]int{6, 33}}; !reflect.DeepEqual(expected, ret) {
t.Errorf("expected %v, got %v", expected, ret)
}
})
}
Expand All @@ -115,15 +120,21 @@ func TestMmapedDoubleArray_CommonPrefixSearchCallback(t *testing.T) {
}
t.Run("keys", func(t *testing.T) {
builder := DoubleArrayBuilder{}
builder.Build(keys, nil)
if err := builder.Build(keys, nil); err != nil {
t.Fatalf("unexpected error, %v", err)
}
var b bytes.Buffer
builder.WriteTo(&b)
if _, err := builder.WriteTo(&b); err != nil {
t.Fatalf("unexpected error, %v", err)
}
mmaped := MmapedDoubleArray{raw: b.Bytes()}
var ids, sizes []int
mmaped.CommonPrefixSearchCallback("電気通信大学大学院大学", 0, func(id, size int) {
if err := mmaped.CommonPrefixSearchCallback("電気通信大学大学院大学", 0, func(id, size int) {
ids = append(ids, id)
sizes = append(sizes, size)
})
}); err != nil {
t.Errorf("unexpected error, %v", err)
}
if expected := []int{2, 3, 4, 5, 6}; !reflect.DeepEqual(expected, ids) {
t.Errorf("ids: expected %v, got %v", expected, ids)
}
Expand Down
16 changes: 8 additions & 8 deletions internal/double_array_mmap_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,21 @@ func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error
return int(unit.value()), len(key), nil
}

// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the ids and it's lengths if found.
func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) (ids, sizes []int, err error) {
// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the array of pairs (id and it's length) if found.
func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) ([][2]int, error) {
var ret [][2]int
nodePos := uint32(0)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
nodePos ^= unit.offset()
for i := offset; i < len(key); i++ {
k := key[i]
nodePos ^= uint32(k)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
if unit.label() != k {
break
Expand All @@ -133,13 +134,12 @@ func (a MmapedDoubleArray) CommonPrefixSearch(key string, offset int) (ids, size
if unit.hasLeaf() {
u, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
ids = append(ids, int(u.value()))
sizes = append(sizes, i+1)
ret = append(ret, [2]int{int(u.value()), i + 1})
}
}
return ids, sizes, nil
return ret, nil
}

// CommonPrefixSearchCallback finds keywords sharing common prefix in an input and callback with id and it's length.
Expand Down
16 changes: 8 additions & 8 deletions internal/double_array_uint32.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,21 @@ func (a DoubleArrayUint32) ExactMatchSearch(key string) (id, size int, err error
return int(unit.value()), len(key), nil
}

// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the ids and it's lengths if found.
func (a DoubleArrayUint32) CommonPrefixSearch(key string, offset int) (ids, sizes []int, err error) {
// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the array of pairs (id and it's length) if found.
func (a DoubleArrayUint32) CommonPrefixSearch(key string, offset int) ([][2]int, error) {
var ret [][2]int
nodePos := uint32(0)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
nodePos ^= unit.offset()
for i := offset; i < len(key); i++ {
k := key[i]
nodePos ^= uint32(k)
unit, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
if unit.label() != k {
break
Expand All @@ -108,13 +109,12 @@ func (a DoubleArrayUint32) CommonPrefixSearch(key string, offset int) (ids, size
if unit.hasLeaf() {
u, err := a.at(nodePos)
if err != nil {
return ids, sizes, err
return ret, err
}
ids = append(ids, int(u.value()))
sizes = append(sizes, i+1)
ret = append(ret, [2]int{int(u.value()), i + 1})
}
}
return ids, sizes, nil
return ret, nil
}

// CommonPrefixSearchCallback finds keywords sharing common prefix in an input and callback with id and it's length.
Expand Down
15 changes: 7 additions & 8 deletions internal/double_array_uint32_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,12 @@ func TestDoubleArrayUint32_CommonPrefixSearch(t *testing.T) {
if err != nil {
t.Errorf("unexpected error, %v", err)
}
ids, sizes, err := a.CommonPrefixSearch("電気通信大学大学院大学", 0)
ret, err := a.CommonPrefixSearch("電気通信大学大学院大学", 0)
if err != nil {
t.Errorf("unexpected error, %v", err)
}
if expected := []int{2, 3, 4, 5, 6}; !reflect.DeepEqual(expected, ids) {
t.Errorf("ids: expected %v, got %v", expected, ids)
}
if expected := []int{6, 12, 18, 27, 33}; !reflect.DeepEqual(expected, sizes) {
t.Errorf("sizes: expected %v, got %v", expected, sizes)
if expected := [][2]int{[2]int{2, 6}, [2]int{3, 12}, [2]int{4, 18}, [2]int{5, 27}, [2]int{6, 33}}; !reflect.DeepEqual(expected, ret) {
t.Errorf("expected %v, got %v", expected, ret)
}
})
}
Expand All @@ -112,10 +109,12 @@ func TestDoubleArrayUint32_CommonPrefixSearchCallback(t *testing.T) {
t.Errorf("unexpected error, %v", err)
}
var ids, sizes []int
a.CommonPrefixSearchCallback("電気通信大学大学院大学", 0, func(id, size int) {
if err := a.CommonPrefixSearchCallback("電気通信大学大学院大学", 0, func(id, size int) {
ids = append(ids, id)
sizes = append(sizes, size)
})
}); err != nil {
t.Errorf("unexpected error, %v", err)
}
if expected := []int{2, 3, 4, 5, 6}; !reflect.DeepEqual(expected, ids) {
t.Errorf("ids: expected %v, got %v", expected, ids)
}
Expand Down
4 changes: 2 additions & 2 deletions trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (
type Trie interface {
// ExactMatchSearch searches TRIE by a given keyword and returns the id and it's length if found.
ExactMatchSearch(key string) (id, size int, err error)
// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the ids and it's lengths if found.
CommonPrefixSearch(key string, offset int) (ids, sizes []int, err error)
// CommonPrefixSearch finds keywords sharing common prefix in an input and returns the array of pairs (id and it's length) if found.
CommonPrefixSearch(key string, offset int) ([][2]int, error)
// CommonPrefixSearchCallback finds keywords sharing common prefix in an input and callback with id and it's length.
CommonPrefixSearchCallback(key string, offset int, callback func(id, size int)) error
}
Expand Down
2 changes: 1 addition & 1 deletion trie_mmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func BenchmarkTRIEMmaped(b *testing.B) {
b.Run("common prefix match search", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, v := range keys {
if ids, _, err := trie.CommonPrefixSearch(v, 0); len(ids) == 0 || err != nil {
if ret, err := trie.CommonPrefixSearch(v, 0); len(ret) == 0 || err != nil {
b.Fatalf("unexpected error, missing a keyword %v, err=%v", v, err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func BenchmarkTRIE(b *testing.B) {
b.Run("common prefix match search", func(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, v := range keys {
if ids, _, err := trie.CommonPrefixSearch(v, 0); len(ids) == 0 || err != nil {
if ret, err := trie.CommonPrefixSearch(v, 0); len(ret) == 0 || err != nil {
b.Fatalf("unexpected error, missing a keyword %v, err=%v", v, err)
}
}
Expand Down

0 comments on commit 3201d12

Please sign in to comment.