commit 3f2bd39bcf5ad904de92375a66246944f0cd45c9 Author: Tracreed Date: Thu Dec 20 00:20:11 2018 +0100 Initial Commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/search.go b/search.go new file mode 100644 index 0000000..8647587 --- /dev/null +++ b/search.go @@ -0,0 +1,113 @@ +package search + +import ( + "sort" + "strings" +) + +var ignoreWords = []string{`a`, `of`, `in`, `the`, `wa`, `ga`, `no`, `ni`, `wo`, `he`, `o`, `ka`} +var replaceCharacters = strings.Split(`〜☆♪・〈〉「」!『』²Ⅱ+[](),.!?\/{}+-_=~"'@#$%^&*|;:<>`, ``) + +// ID ... +type ID struct { + ID int + Score float64 + Title []string +} + +// Search ... +type Search struct { + Titles map[interface{}][][]string + IgnoreWords []string + RemoveCharacters []string +} + +// CleanSearch ... +func CleanSearch(title string) []string { + s := []string{} + for _, c := range replaceCharacters { + title = strings.Replace(title, c, ` `, -1) + } + for _, v := range strings.Split(title, ` `) { + matched := false + if v == `` || v == ` ` { + continue + } + for _, w := range ignoreWords { + if v == w { + matched = true + } + } + if !matched { + s = append(s, strings.ToLower(v)) + } + } + return s +} + +// IndexSearch ... +func (DB *Search) IndexSearch(id interface{}, st [][]string) { + if DB.Titles == nil { + DB.Titles = make(map[interface{}][][]string) + } + for _, t := range st { + DB.Titles[id] = append(DB.Titles[id], t) + } + +} + +// Match ... +func (DB *Search) Match(Title string) []interface{} { + IDS := []ID{} + title := CleanSearch(strings.ToLower(Title)) +mainLoop: + for i := range DB.Titles { + for _, t := range DB.Titles[i] { + if len(t) == 0 { + continue + } + + sim := similarity(t, title) + if sim > 0 { + IDS = append(IDS, ID{ID: i.(int), Score: sim, Title: t}) + continue mainLoop + } + } + } + sort.Slice(IDS, func(i, j int) bool { + return IDS[i].Score > IDS[j].Score + }) + + ids := []interface{}{} + for _, v := range IDS { + ids = append(ids, v.ID) + } + return ids +} + +func similarity(a, b []string) float64 { + var s float64 + var matched []int +loop: + for _, i := range a { + for f, l := range b { + if i == l && !intInSlice(f, matched) { + s++ + matched = append(matched, f) + continue loop + } else { + s = s - 0.125 + } + } + } + return s +} + +func intInSlice(a int, list []int) bool { + for _, b := range list { + if b == a { + return true + } + } + return false +}