Я играл в IRB и обнаружил, что:
("A".."Z").to_a
(конечно) возвращает:
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
Но ("A".."Å").to_a
возвращает:
=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD",
"AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ",
"AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD",
"BE", "BF", "BG", "BH", "BI", "BJ", "BK", "BL", "BM", "BN", "BO", "BP", "BQ",
"BR", "BS", "BT", "BU", "BV", "BW", "BX", "BY", "BZ", "CA", "CB", "CC", "CD",
...
"ZR", "ZS", "ZT", "ZU", "ZV", "ZW", "ZX", "ZY", "ZZ"]
Я пробовал читать о методе to_a
, но не нашел ничего, объясняющего такое поведение.
Почему это происходит?
("A".."Å")
работает аналогично "A".upto("Å")
. Теперь о String#upto
можно сказать две вещи:
String#succ
для получения следующего значения."Å" кодируется двумя байтами:
"Å".bytes # => [195, 133]
В то время как "А" закодирован всего в одном:
"A".bytes # => [65]
Приступим к итерации:
"A".sucC# => "B"
"B".sucC# => "C"
# ...
"Y".sucC# => "Z"
"Z".sucC# => "AA"
"AA".sucC# => "AB"
# ...
"ZY".sucC# => "ZZ"
"ZZ".sucC# => "AAA"
Теперь «ААА» все еще «меньше», чем "Å":
"AAA" < "Å" # => true
Но он имеет размер 3 байта:
"AAA".bytes # => [65, 65, 65]
Следовательно, согласно спецификация, диапазон здесь останавливается.
@mudasobwa, вы правы. Я почему-то неправильно это запомнил. Создавал ли он диапазоны в предыдущих версиях?
Полагаю, что так. Крякает как ассортимент :)
Уау! Спасибо @ndn. Теперь я понимаю!
В спецификации указано "количество символов", а не количество байтов.
@ Стефан, верно. Но разумно предположить, что именно это и происходит под капотом. Иначе остановился бы на AA
.
Исправьте формулировку в «
("A".."Å")
- это сокращение от"A".upto("Å")
» - первое - это диапазон, второе - это вызов метода, возвращающего экземпляр перечислителя. У них нет ничего общего, за исключением вызова#to_a
для обоих результатов с одним и тем же результатом.