search/search.go

120 lines
2.1 KiB
Go

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
}