search/search.go

120 lines
2.1 KiB
Go
Raw Permalink Normal View History

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