search using levenshtein distance

Former-commit-id: c40738a317d92952b6c3a5a57d129a41b96160fe [formerly c40738a317d92952b6c3a5a57d129a41b96160fe [formerly 5382c4e245f714e496aaba450b12851abcd68410 [formerly 93bc7a8b9d3381a627fa9531d4908e3598298905]]]
Former-commit-id: 20d2a32baa3a9eb882fbe8a022f784cb4558ccc3
Former-commit-id: 6f28c974b0ae40f06ca301ffdbd775c998fa0f3d [formerly 8b9d7ea7735a9388f414bedc7181a009ca7e7c03]
Former-commit-id: 24e129d95cfa46cfb0789a6a27a4f94ed0cc41f0
pull/15/head
Miguel Mota 6 years ago
parent bbd1824635
commit ab93233d4f

@ -1,14 +1,18 @@
package cointop
func (ct *Cointop) getCurrentPage() int {
func (ct *Cointop) currentPage() int {
return ct.page + 1
}
func (ct *Cointop) getTotalPages() int {
func (ct *Cointop) currentDisplayPage() int {
return ct.page + 1
}
func (ct *Cointop) totalPages() int {
return (ct.getListCount() / ct.perpage) + 1
}
func (ct *Cointop) getTotalPerPage() int {
func (ct *Cointop) totalPerPage() int {
return ct.perpage
}
@ -29,7 +33,7 @@ func (ct *Cointop) highlightRow(idx int) error {
ox, _ := ct.tableview.Origin()
cx, _ := ct.tableview.Cursor()
_, sy := ct.tableview.Size()
perpage := ct.getTotalPerPage()
perpage := ct.totalPerPage()
p := idx % perpage
oy := (p / sy) * sy
cy := p % sy

@ -3,6 +3,8 @@ package cointop
import (
"regexp"
"strings"
"github.com/miguelmota/cointop/pkg/levenshtein"
)
func (ct *Cointop) openSearch() error {
@ -38,25 +40,34 @@ func (ct *Cointop) doSearch() error {
func (ct *Cointop) search(q string) error {
q = strings.TrimSpace(strings.ToLower(q))
idx := -1
min := -1
for i := range ct.allcoins {
coin := ct.allcoins[i]
if strings.ToLower(coin.Name) == q {
ct.goToGlobalIndex(i)
return nil
name := strings.ToLower(coin.Name)
symbol := strings.ToLower(coin.Symbol)
if symbol == q {
idx = i
break
}
}
for i := range ct.allcoins {
coin := ct.allcoins[i]
if strings.ToLower(coin.Symbol) == q {
ct.goToGlobalIndex(i)
return nil
dist := levenshtein.Distance(name, q)
if min == -1 {
min = dist
}
if dist <= min {
idx = i
min = dist
}
}
if idx > -1 && min <= 6 {
ct.goToGlobalIndex(idx)
}
return nil
}
func (ct *Cointop) goToGlobalIndex(idx int) error {
perpage := ct.getTotalPerPage()
perpage := ct.totalPerPage()
atpage := idx / perpage
ct.setPage(atpage)
rowIndex := (idx % perpage)

@ -9,8 +9,8 @@ import (
func (ct *Cointop) updateStatusbar(s string) {
ct.update(func() {
ct.statusbarview.Clear()
currpage := ct.getCurrentPage()
totalpages := ct.getTotalPages()
currpage := ct.currentDisplayPage()
totalpages := ct.totalPages()
base := "[q]uit [?]help [c]hart [/]search"
fmt.Fprintln(ct.statusbarview, pad.Right(fmt.Sprintf("%v [← →]page %v/%v %s", base, currpage, totalpages, s), ct.maxtablewidth, " "))
})

@ -0,0 +1,57 @@
package levenshtein
// Distance Levenshtein distance
// The Levenshtein distance between two strings is defined as the minimum
// number of edits needed to transform one string into the other, with the
// allowable edit operations being insertion, deletion, or substitution of
// a single character
// http://en.wikipedia.org/wiki/Levenshtein_distance
//
// This implemention is optimized to use O(min(m,n)) space.
// It is based on the optimized C version found here:
// http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
func Distance(str1, str2 string) int {
var cost, lastdiag, olddiag int
s1 := []rune(str1)
s2 := []rune(str2)
lenS1 := len(s1)
lenS2 := len(s2)
column := make([]int, lenS1+1)
for y := 1; y <= lenS1; y++ {
column[y] = y
}
for x := 1; x <= lenS2; x++ {
column[0] = x
lastdiag = x - 1
for y := 1; y <= lenS1; y++ {
olddiag = column[y]
cost = 0
if s1[y-1] != s2[x-1] {
cost = 1
}
column[y] = min(
column[y]+1,
column[y-1]+1,
lastdiag+cost)
lastdiag = olddiag
}
}
return column[lenS1]
}
func min(a, b, c int) int {
if a < b {
if a < c {
return a
}
} else {
if b < c {
return b
}
}
return c
}
Loading…
Cancel
Save