Как эффективно разделить очень длинную (несколько миллионов символов) строку после каждого n-го символа в Ruby? - PullRequest
0 голосов
/ 23 апреля 2019

Допустим, у меня есть строка

string = "hellohellohey"

Я хочу разделить его на каждый второй символ, чтобы он выглядел следующим образом

string = ["he","ll","oh","el","lo","he","y"]

Я пытался использовать метод scan(/.{2}/), но если элемент массива нельзя разделить на 2, он не работает.

Редактировать: Необходимо сообщить вам, что пример с 2 символами был примером. Я делаю что-то большое, поэтому буду разбивать его на каждые 8 ​​ миллион символов. Так что разделение его на отдельные символы и использование each_slice здесь не работает. Мой ноутбук просто зависает.

Ответы [ 3 ]

3 голосов
/ 23 апреля 2019

Точка соответствует любому символу, кроме новой строки. Вы пытаетесь сопоставить 2 раза любой символ, и он не будет соответствовать последнему символу, если строка нечетной длины.

Вы можете использовать квантификатор {1,2}, который является жадным, поэтому сначала пытается найти совпадение 2 раза.

.{1,2}

См. демо

Если вы хотите сопоставлять только строчные буквы a-z, вы также можете использовать [a-z] вместо точки.

3 голосов
/ 24 апреля 2019

При обработке (очень) больших строк может быть полезно обернуть их в StringIO. Он обеспечивает эффективный файловый доступ к строке.

Например, вы можете прочитать все n символов с помощью StringIO#each:

string = "hellohellohey"
string_io = StringIO.new(string)

string_io.each(5) do |substring|
  p substring
end

Выход:

"hello"
"hello"
"hey"
3 голосов
/ 23 апреля 2019

Вы можете объединить несколько методов, как показано ниже:

string = 'hellohellohey'
string.chars.each_slice(2).map { |s| s.join }
# => ["he", "ll", "oh", "el", "lo", "he", "y"]

# символов преобразует строку в массив символов.

# each_slice разбивает массив на необходимое количество частей.

Обновление - без промежуточного / временного массива

Согласно комментариям, благодаря @Cary Swoveland, временного массива можно избежать следующим образом.

string.each_char.each_slice(2).map { |s| s.join }

# each_char дает перечислитель каждого символа.

...