Определение языка в строке
Необходимо выяснить язык в строке. Если в ней содержатся кириллические символы, значит она написана на русском языке. Если кириллических символов нет - значит на английском. Для этой цели использую регулярные выражения:
import (
"regexp"
)
func main() {
str := "Некая строка c кириллическими символами"
re := regexp.MustCompile("[А-Яа-я]+?") //проверяем на киррилические символы
isRussian := re.MatchString(str)
if isRussian {
...
}
}
Есть ли более эффективный способ узнать, на каком языке написана строка? Языков только два - русский и английский.
Ответы (2 шт):
Если предполагается, что не будет смешанных строк, то можно сделать так:
func IsRusByUnicode(str string) bool {
for _, r := range str {
if unicode.Is(unicode.Cyrillic, r) {
return true
}
}
return false
}
Это будет быстрее, чем RegExp:
package language
import "testing"
var result bool
func BenchmarkIsRusByUnicode(b *testing.B) {
b.ReportAllocs()
var r bool
for i := 1; i < b.N; i++ {
r = IsRusByUnicode("Некая строка c кириллическими символами")
}
result = r
}
func BenchmarkIsRusByRegexp(b *testing.B) {
b.ReportAllocs()
var r bool
for i := 1; i < b.N; i++ {
r = IsRusByRegexp("Некая строка c кириллическими символами")
}
result = r
}
Результаты тестирования:
BenchmarkIsRusByUnicode-8 85523263 12.6 ns/op 0 B/op 0 allocs/op
BenchmarkIsRusByRegexp-8 13899225 82.8 ns/op 0 B/op 0 allocs/op
UPD: заменил проверку вхождения символа в русский алфавит на более корректную.
Самый быстрый (и он же, самый простой) способ:
func IsEngByLoop(str string) bool {
for i := 0; i < len(str); i++ {
if str[i] > unicode.MaxASCII {
return false
}
}
return true
}
Раз вы уверены, что имеете дело только с двумя языками, то достаточно определить, являются ли все символы строки ASCII символами. Если да, то строка написана на Английском, если нет - то на каком-то другом (в вашем случае, это Русский).
Результаты бенчмарка для случая, когда строка на Русском:
goos: windows
goarch: amd64
BenchmarkIsRusByRegexp-2 521700 2045 ns/op 840 B/op 10 allocs/op
BenchmarkIsRusByUnicode-2 63156564 18.8 ns/op 0 B/op 0 allocs/op
BenchmarkIsEngByRune-2 100000000 11.2 ns/op 0 B/op 0 allocs/op
BenchmarkIsEngByLoop-2 326068348 3.70 ns/op 0 B/op 0 allocs/op
для случая, когда строка на Английском:
BenchmarkIsRusByRegexp-2 285699 3574 ns/op 840 B/op 10 allocs/op
BenchmarkIsRusByUnicode-2 3550089 340 ns/op 0 B/op 0 allocs/op
BenchmarkIsEngByRune-2 27271363 42.9 ns/op 0 B/op 0 allocs/op
BenchmarkIsEngByLoop-2 39998400 30.2 ns/op 0 B/op 0 allocs/op
Для сравнения, в тесте принимали участие функция из ответа выше и функция с итерированием при помощи range:
func IsEngByRune(str string) bool {
for _, r := range str {
if r > unicode.MaxASCII {
return false
}
}
return true
}