Ruby/Избранное с RubyNews: различия между версиями

Содержимое удалено Содержимое добавлено
Строка 161:
 
Рассмотрим классическую задачу генерации пароля. Алгоритм решения прост до безобразия: формируем словарь символов из которых будет состоять пароль и затем случайным образом выбираем символы из этого словаря. Результат формируется в виде строки и выводится на экран. Для решения данной задачи "в одну строчку" мы будем использовать возможность инициализации массива через блок, которая появилась в Ruby начиная с версии 1.8. Итак, сразу оговоримся, что наш пароль будет состоять из латинских букв верхнего и нижнего регистра, а также из арабских цифр. Решения данной задачи тогде будет выглядеть так:
<codesource lang=ruby>chars = ['0'..'9','a'..'z','A'..'Z'].map{ |r| r.to_a }.flatten
puts Array.new(8){ chars[ rand( chars.size ) ] }.join</codesource>
Теперь на примере решения данной задачи, хотелось бы подемонстрировать применение новых методов генерации псевдослучайной последовательности. Создадим мы эти методы для класса <code>Integer</code> (целые числа), <code>String</code> (строки), <code>Array</code> (массивы) и <code>Range</code> (диапазоны). Начнем с самого простого - с целых чисел:
<codesource lang=ruby>class Integer
def rand
Kernel.rand( self )
end
end</codesource>
Как видно из описания метода, он генерит случайное число от 0 до <code>self</code>, исключая self. Теперь применим вновь созданный метод к решению нашей задачи:
<codesource lang=ruby>chars = ['0'..'9','a'..'z','A'..'Z'].map{ |r| r.to_a }.flatten
puts Array.new(8){ chars[ chars.size.rand ] }.join</codesource>
Теперь рассмотрим метод rand для массивов. Дальше мы его будем использовать для описания методов других классов. Итак, описание метода rand для класса <code>Array</code>:
<codesource lang=ruby>class Array
def rand
self[ size.rand ]
end
end</codesource>
Как видно из описания метода, он возвращает произвольный элемент массива. Теперь перепишем решение задачи генераци пароля через вышеописанный метод:
<codesource lang=ruby>chars = ['0'..'9','a'..'z','A'..'Z'].map{ |r| r.to_a }.flatten
puts Array.new(8){ chars.rand }.join</codesource>
По-моему получилось неплохо. Давайте смотреть дальше. Теперь у нас на очереди метод <code>rand</code> для класса <code>String</code>:
<codesource lang=ruby>class String
def rand
self.split("").rand
end
end</codesource>
Как видно, данный метод возвращает произвольный символ строки. Для простоты реализации он реализован через использование метода <code>Array#rand</code>. Перепишем решение задачи генерации пароля через вровь написанный нами метод:
<codesource lang=ruby>chars = ['0'..'9','a'..'z','A'..'Z'].map{ |r| r.to_a }.flatten.join
puts Array.new(8){ chars.rand }.join</codesource>
Итак, остался последний класс, который еще пока не имеет метода <code>rand</code>. Для класса <code>Range</code> мы будем использовать тот же поход, что и для <code>String</code>, а именно сведением класса <code>Range</code> к массиву, а затем уже выборкой случайного элемента из этого диапазона. Смотрим реализацию:
<codesource lang=ruby>class Range
def rand
to_a.rand
end
end</codesource>
Переписываем решение исходной задачи через использование метода Range#rand (последний раз за сегодня):
<codesource lang=ruby>chars = ['0'..'9','a'..'z','A'..'Z'].map{ |r| r.to_a }.flatten
puts Array.new(8){ chars[ (0...chars.size).rand ] }.join</codesource>
Надеюсь, что я не сильно загрузил неискушенного читателя. Если загрузил, то включите музыку и разгрузитесь. :-)