Определение языка в строке

Необходимо выяснить язык в строке. Если в ней содержатся кириллические символы, значит она написана на русском языке. Если кириллических символов нет - значит на английском. Для этой цели использую регулярные выражения:

import (
    "regexp"
)

func main() {
    str := "Некая строка c кириллическими символами"
    re := regexp.MustCompile("[А-Яа-я]+?") //проверяем на киррилические символы
    isRussian := re.MatchString(str)

    if isRussian {
        ...
    }
}

Есть ли более эффективный способ узнать, на каком языке написана строка? Языков только два - русский и английский.


Ответы (2 шт):

Автор решения: Pavel Parshin

Если предполагается, что не будет смешанных строк, то можно сделать так:

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: заменил проверку вхождения символа в русский алфавит на более корректную.

→ Ссылка
Автор решения: zed

Самый быстрый (и он же, самый простой) способ:

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
}
→ Ссылка