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 }