Книга: Программирование на языке Ruby
6.2.3. Обход диапазона
6.2.3. Обход диапазона
Обычно диапазон можно обойти. Для этого класс, которому принадлежат границы диапазона, должен предоставлять осмысленный метод succ
(следующий).
(3..6).each {|x| puts x } # Печатаются четыре строки
# (скобки обязательны).
Пока все хорошо. И тем не менее будьте очень осторожны при работе со строковыми диапазонами! В классе String
имеется метод succ
, но он не слишком полезен. Пользоваться этой возможностью следует только при строго контролируемых условиях, поскольку метод succ
определен не вполне корректно. (В определении используется, скорее, «интуитивно очевидный», нежели лексикографический порядок, поэтому существуют строки, для которых «следующая» не имеет смысла.)
r1 = "7".."9"
r2 = "7".."10"
r1.each {|x| puts x } # Печатаются три строки.
r2.each {|x| puts x } # Ничего не печатается!
Предыдущие примеры похожи, но ведут себя по-разному. Отчасти причина в том, что границы второго диапазона — строки разной длины. Мы ожидаем, что в диапазон входят строки "7"
, "8"
, "9"
и "10"
, но что происходит на самом деле?
При обходе диапазона r2
мы начинаем со значения "7"
и входим в цикл, который завершается, когда текущее значение окажется больше правой границы. Но ведь "7"
и "10"
— не числа, а строки, и сравниваются они как строки, то есть лексикографически. Поэтому левая граница оказывается больше правой, и цикл не выполняется ни разу.
А что сказать по поводу диапазонов чисел с плавающей точкой? Такой диапазон можно сконструировать и, конечно, проверить, попадает ли в него конкретное число. Это полезно. Но обойти такой диапазон нельзя, так как метод succ
отсутствует.
fr = 2.0..2.2
fr.each {|x| puts x } # Ошибка!
Почему для чисел с плавающей точкой нет метода succ
? Теоретически можно было бы увеличивать число на некоторое приращение. Но величина такого приращения сильно зависела бы от конкретной машины, при этом даже для обхода «небольшого» диапазона понадобилось бы гигантское число итераций, а полезность такой операции весьма сомнительна.
- 6.2.2. Нахождение границ диапазона
- Определение диапазона адресов
- Использование свойств Cells для определения диапазона
- Зона «необходимо и достаточно»
- Почему необходима миграция
- Уменьшение времени, необходимого для резервного копирования и восстановления
- Обход дерева
- Определение необходимого системного вызова
- Добавление списка необходимых предметов
- Глава 2. Что необходимо для беспроводной связи
- Можно ли избавиться от необходимости использовать двойной щелчок кнопкой мыши при открытии папки?
- 7.6. Обход элементов массива