Skip to content

Commit 6c482ec

Browse files
committed
add levenshtein.go and metaphonebr.go to build the search for names, and it's similarity's
1 parent 9cd4af2 commit 6c482ec

File tree

7 files changed

+51694
-29
lines changed

7 files changed

+51694
-29
lines changed

controllers/controller.go

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,63 @@ package controllers
22

33
import (
44
"github.com/Darklabel91/API_Names/database"
5+
"github.com/Darklabel91/API_Names/metaphone"
56
"github.com/Darklabel91/API_Names/models"
67
"github.com/gin-gonic/gin"
78
"net/http"
9+
"sort"
10+
"strings"
811
)
912

10-
func GetAllNames(c *gin.Context) {
13+
func SearchSimilarNames(c *gin.Context) {
1114
var names []models.NameType
12-
database.Db.Find(&names)
1315

14-
c.JSON(200, names)
16+
//Name to be searched
17+
name := c.Params.ByName("name")
18+
mtf := metaphone.Pack(name)
19+
20+
database.Db.Where("metaphone = ?", metaphone.Pack(name)).Find(&names)
21+
22+
if len(names) == 0 {
23+
c.JSON(http.StatusNotFound, gin.H{"Not found": "metaphone not found", "metaphone": mtf})
24+
return
25+
}
26+
27+
var similarNames []string
28+
for _, n := range names {
29+
if metaphone.SimilarityBetweenWords(strings.ToLower(name), strings.ToLower(n.Name)) >= 0.8 {
30+
similarNames = append(similarNames, n.Name)
31+
varWords := strings.Split(n.NameVariations, "|")
32+
for _, vw := range varWords {
33+
if vw != "" {
34+
similarNames = append(similarNames, strings.TrimSpace(vw))
35+
}
36+
}
37+
}
38+
39+
if len(similarNames) == 0 {
40+
similarNames = append(similarNames, n.Name)
41+
varWords := strings.Split(n.NameVariations, "|")
42+
for _, vw := range varWords {
43+
if vw != "" {
44+
similarNames = append(similarNames, strings.TrimSpace(vw))
45+
}
46+
}
47+
}
48+
49+
sort.Strings(similarNames)
50+
51+
}
52+
53+
c.JSON(200, gin.H{
54+
"Name": strings.ToUpper(name),
55+
"metaphone": mtf,
56+
"name_variations": similarNames,
57+
})
58+
1559
}
1660

61+
//CreateName create new name on database of type NameType
1762
func CreateName(c *gin.Context) {
1863
var name models.NameType
1964
if err := c.ShouldBindJSON(&name); err != nil {
@@ -25,6 +70,7 @@ func CreateName(c *gin.Context) {
2570
c.JSON(http.StatusOK, name)
2671
}
2772

73+
//SearchNameByID read name by id
2874
func SearchNameByID(c *gin.Context) {
2975
var name models.NameType
3076

@@ -39,19 +85,7 @@ func SearchNameByID(c *gin.Context) {
3985
c.JSON(http.StatusOK, name)
4086
}
4187

42-
func SearchNameByMetaphone(c *gin.Context) {
43-
var name models.NameType
44-
metaphone := c.Params.ByName("mtf")
45-
46-
database.Db.Where(&models.NameType{Metaphone: metaphone}).First(&name)
47-
if name.ID == 0 {
48-
c.JSON(http.StatusNotFound, gin.H{"Not found": "name id not found"})
49-
return
50-
}
51-
52-
c.JSON(http.StatusOK, name)
53-
}
54-
88+
//DeleteName delete name off database by id
5589
func DeleteName(c *gin.Context) {
5690
var name models.NameType
5791
id := c.Params.ByName("id")
@@ -65,6 +99,7 @@ func DeleteName(c *gin.Context) {
6599
c.JSON(http.StatusOK, gin.H{"data": "name data deleted"})
66100
}
67101

102+
//UpdateName update name by id
68103
func UpdateName(c *gin.Context) {
69104
var name models.NameType
70105
id := c.Param("id")

database/name_types.csv

Lines changed: 50744 additions & 0 deletions
Large diffs are not rendered by default.

levenshtein/levenshtein.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package levenshtein
2+
3+
// Distance The levenshtein distance between two strings is defined as the minimum
4+
// number of edits needed to transform one string into the other, with the
5+
// allowable edit operations being insertion, deletion, or substitution of
6+
// a single character
7+
// http://en.wikipedia.org/wiki/Levenshtein_distance
8+
//
9+
// This implementation is optimized to use O(min(m,n)) space.
10+
// It is based on the optimized C version found here:
11+
// http://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Levenshtein_distance#C
12+
func Distance(str1, str2 string) int {
13+
var (
14+
cost, lastDiag, oldDiag int
15+
)
16+
17+
s1 := []rune(str1)
18+
s2 := []rune(str2)
19+
20+
lenS1 := len(s1)
21+
lenS2 := len(s2)
22+
23+
column := make([]int, lenS1+1)
24+
25+
for y := 1; y <= lenS1; y++ {
26+
column[y] = y
27+
}
28+
29+
for x := 1; x <= lenS2; x++ {
30+
column[0] = x
31+
lastDiag = x - 1
32+
for y := 1; y <= lenS1; y++ {
33+
oldDiag = column[y]
34+
cost = 0
35+
if s1[y-1] != s2[x-1] {
36+
cost = 1
37+
}
38+
column[y] = min(
39+
column[y]+1,
40+
column[y-1]+1,
41+
lastDiag+cost)
42+
lastDiag = oldDiag
43+
}
44+
}
45+
return column[lenS1]
46+
}
47+
48+
func min(a, b, c int) int {
49+
if a < b {
50+
if a < c {
51+
return a
52+
}
53+
} else {
54+
if b < c {
55+
return b
56+
}
57+
}
58+
return c
59+
}

0 commit comments

Comments
 (0)