Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

Как быстрее измерить длину строки в Go?

Интересная штука, с которой сталкиваются начинающие разработчики в Гоу — как измерить длину строки в этом языке. То есть речь не идёт даже о быстроте, как, чёрт возьми, вообще это сделать?

Встроенная функция len возвращает длину в байтах, именно поэтому англоязычные разработчики часто и не знают, что проблема есть — строки латиницы, что в байтах, что в символах (в Гоу они называются «руны») занимают одинаково.

Я знаю два способа измерить длину строки:

package main

import ("io/ioutil"; "unicode/utf8")

func main() {
    bytes, _ := ioutil.ReadFile("test.txt")

    // считаем сколько рун встречается в строке
    print(utf8.RuneCountInString(string(bytes)))

    print("\n")

    // считаем длину массива рун
    print(len([]rune(string(bytes))))
}

По работе понадобилось измерить длину строки быстро — у меня здоровый цикл, где она постоянно измеряется, оказалось, что в тысяче итераций на тексте книги «На всех пара́х» Терри Пратчетта разница в две секунды — выигрывает преобразование в массив «рун».

Нужен быстрый способ — используйте len([]rune(…)).

6 комментариев
Кальянов Дмитрий (dmitry-vk.livejournal.com) 2014

Боюсь показаться занудой. Но руны — это кодовые точки, а не символы (хотя и достаточно близко для русского языка). Но иногда это может оказаться неожиданным (особенно — в контексте безопасности или криптографии).

Евгений Степанищев (bolknote.ru) 2014

Комментарий для dmitry-vk.livejournal.com:

Не понял комментария, раскройте мысль, пожалуйста!

Кальянов Дмитрий (dmitry_vk.livejournal.com) 2014

Некоторые буквы (например, такие, как «ё») в юникоде имеют несколько представлений: в виде precomposed character (тогда буква занимает одну руну) и в виде пары символ + combining character (тогда буква занимает две руны: одна руна — базовый символ, и еще одна руна — комбинирующий символ).

Приведу пример кода:
http://pastebin.com/hAvYX5ya

Павел Павлович Форкерт (blog.fxposter.org) 2014

Советую почитать вот это (про JavaScript, но главное не в этом): http://mathiasbynens.be/notes/javascript-unicode

Евгений Степанищев (bolknote.ru) 2014

Комментарий для dmitry_vk.livejournal.com:

Дмитрий, вы перепутали символы и буквы. Все буквы — символы, не все символы — буквы.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для blog.fxposter.org:

Спасибо, но тему Юникода я знаю очень хорошо.