package stringutils import ( "encoding/json" "fmt" "strings" "unicode" "unicode/utf8" "github.com/xrash/smetrics" ) var whitespace = rune(' ') // RemoveSpecialCharacters ... func RemoveSpecialCharacters(s string) string { return strings.Map( func(r rune) rune { if r == '-' { return -1 } if !unicode.IsLetter(r) && !unicode.IsDigit(r) { return whitespace } return r }, s, ) } // AdvancedStringSimilarity is like StringSimilarity but boosts the value if a appears directly in b. func AdvancedStringSimilarity(a string, b string) float64 { if a == b { return 10000000 } normalizedA := strings.Map(keepLettersAndDigits, a) normalizedB := strings.Map(keepLettersAndDigits, b) if normalizedA == normalizedB { return 100000 } s := StringSimilarity(a, b) if strings.Contains(normalizedB, normalizedA) { s += 0.6 if strings.HasPrefix(b, a) { s += 0.4 } } return s } // StringSimilarity returns 1.0 if the strings are equal and goes closer to 0 when they are different. func StringSimilarity(a string, b string) float64 { return smetrics.JaroWinkler(a, b, 0.7, 4) } // Capitalize returns the string with the first letter capitalized. func Capitalize(s string) string { if s == "" { return "" } r, n := utf8.DecodeRuneInString(s) return string(unicode.ToUpper(r)) + s[n:] } // Plural returns the number concatenated to the proper pluralization of the word. func Plural(count int, singular string) string { if count == 1 || count == -1 { return fmt.Sprintf("%d %s", count, singular) } switch singular { case "activity": singular = "activitie" case "company": singular = "companie" } return fmt.Sprintf("%d %ss", count, singular) } // ContainsUnicodeLetters tells you if unicode characters are inside the string. func ContainsUnicodeLetters(s string) bool { return len(s) != len([]rune(s)) } // PrettyPrint prints the object as indented JSON data on the console. func PrettyPrint(obj interface{}) { // Currently, MarshalIndent doesn't support tabs. // Change this back to using \t when it's implemented. // See: https://github.com/json-iterator/go/pull/273 pretty, _ := json.MarshalIndent(obj, "", " ") fmt.Println(string(pretty)) } // keepLettersAndDigits removes everything but letters and digits when used in strings.Map. func keepLettersAndDigits(r rune) rune { if !unicode.IsLetter(r) && !unicode.IsDigit(r) { return -1 } return r }