package search import ( "sort" "strings" ) // ID ... type ID struct { Key interface{} Score float64 Title []string } // Search ... type Search struct { Words map[interface{}][][]string IgnoreWords []string RemoveCharacters []string } // CleanSearch ... func (DB *Search) CleanSearch(title string) []string { s := []string{} for _, c := range DB.RemoveCharacters { title = strings.Replace(title, c, ` `, -1) } for _, v := range strings.Split(title, ` `) { matched := false if v == `` || v == ` ` { continue } for _, w := range DB.IgnoreWords { if v == w { matched = true } } if !matched { s = append(s, strings.ToLower(v)) } } return s } // Add ... func (DB *Search) Add(key interface{}, st [][]string) { if DB.Words == nil { DB.Words = make(map[interface{}][][]string) } DB.Words[key] = append(DB.Words[key], st...) } // Ignore ... func (DB *Search) Ignore(list []string) { DB.IgnoreWords = list } // Replace ... func (DB *Search) Replace(list []string) { DB.RemoveCharacters = list } // Match ... func (DB *Search) Match(Title string) []interface{} { IDS := []ID{} title := DB.CleanSearch(strings.ToLower(Title)) for k, v := range DB.Words { tempKeys := []ID{} for _, t := range v { sim := similarity(t, title) if sim > 0 { tempKeys = append(tempKeys, ID{Key: k, Score: sim, Title: t}) } } if len(tempKeys) > 0 { sort.Slice(tempKeys, func(i, j int) bool { return tempKeys[i].Score > tempKeys[j].Score }) IDS = append(IDS, tempKeys[0]) } } sort.Slice(IDS, func(i, j int) bool { return IDS[i].Score > IDS[j].Score }) keys := []interface{}{} for _, v := range IDS { keys = append(keys, v.Key) } return keys } 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 if i != l { s = s - ((float64(len(i)) * 0.1) * (0.125 / 2)) } } } return s } func intInSlice(a int, list []int) bool { for _, b := range list { if b == a { return true } } return false }