Занятие 4
def simple_iterator yield 2 # передача управления в блок итератора yield 7 yield 1 end simple_iterator {|i| puts i } 15. Итераторы изнутри
def fibonacci(limit) a = 1 b = 1 yield a while b < limit yield b a, b = b, a+b end fibonacci(20) {|f| print f, } puts Числа Фибоначчи с использованием метода -итератора
Задания 28) Напишите метод итератор #my_each в классе Array, который работал бы аналогично #each.
class Array def my_each i = 0 while i < self.length yield self[i] i += 1 end [1,8,4,6].my_each {|i| puts i }
puts [1,8,4,6].collect {|i| i + 1 }.inspect puts [1,8,4,6].collect {|i| (i + 1).to_s }.join( ) puts [1,8,4,6].select {|i| i < 5 } puts [1,8,4,6].reject {|i| i < 5 } puts [1,8,4,6].reject {|i| i < 5}.join(, ) Методы модуля Enumerable #collect, #select, #reject
16. Пишем класс множества (Set). Задача - написать класс множества, которое можно было бы использовать следующим образом: require "my_set.rb" lexicon1 = Set.new lexicon2 = Set.new some_text.split{|word| lexicon1.add word } another_text.split{|word| lexicon2.add word } print уникальных слов в тексте 1:, lexicon1.size,\n puts (lexicon1 – lexicon2).inspect # разница множеств puts (lexicon1 + lexicon2).inspect # объединение # 2 множеств # пересечение 2 множеств puts (lexicon1.intersect_with(lexicon2)).inspect
Чем отличается Hash от Set ? Set как наследник класса Hash. Основные методы: #new, #add, #inspect Отредактируйте файл my_set.rb: class Set < Hash def initialize() # можно опустить super end def add(element) self[element]=true end def inspect "< " + self.keys.collect{|e| e.inspect }.join( ) + " >" end
Пробуем Set : irb> require "set.rb" irb> set = Set.new irb> set.add 2 irb> set irb> set.add "hello" irb> set irb> set.add 2 irb> set
Так как Set – наследник Hash, многие методы уже унаследованы, например, #delete : irb> hash = Hash.new irb> hash["Peter"]=34 irb> hash["John"]=45 irb> hash irb> hash.delete "Peter" irb> hash irb> require "set.rb" irb> set = Set.new irb> set.add "Peter" irb> set.add "John" irb> set irb> set.delete "Peter" irb> set
Задания 29) Перепишите конструктор так, чтобы он мог принимать опциональный аргумент – массив, элементы которого становились бы элементами множества. set = Set.new([2, hi])#=> Помощь: значение по умолчанию задается следующим образом: def say (arg1, arg2 = hello) return #{arg2}, #{arg1} end say(world) #=> hello, world say(world, bye) #=> bye, world
def initialize(a=[]) super a.each do |e| self.add e end
Задания 30) Добавьте метод
def
Задания 31) Напишите метод #to_a, который бы возвращал массив, состоящий из элементов множества
def to_a self.keys end alias_method :to_a, :keys Однако если метод #to_a класса Set – это то же самое, что и метод #keys класса Hash (наследуемого классом Set ), то можно просто добавить еще одно имя для метода #keys :
Задания 32) Напишите метод #has_element?, который бы проверял наличие элемента в множестве.
def has_element?(element) self.has_key? element end alias :has_element? :has_key? #has_element? == #has_key?
Задания 33) Напишите метод-итератор #each, который бы перебирал все элементы множества.
def each self.each_key do |e| yield e end alias_method :each :each_key #each_key делает как раз то, что нам нужно, поэтому мы создаем для #each_key новое имя. При этом мы перекрываем оригинальный #each класса Hash.
Задания 34) Напишите метод ==, который бы принимал в качестве аргумента другое множество и сравнивал бы их.
def ==(another_set) return false if another_set.size != self.size another_set.each do |e| return false unless self.has_element? e end return true end
Задания 35) Напишите метод #rando m, который бы возвращал случайный элемент множества. Воспользуйтесь справкой ri rand
def random self.keys[rand self.length] end
Задания 36) Напишите метод #is_superset_of, который бы принимал в качестве аргумента другое множество и проверял, не является ли текущий объект надмножеством множества-аргумента. Надмножество включает все элементы множества. a = Set.new([1,hi,3,10]) b = Set.new([10, hi]) с = Set.new([10, hi, 23]) a.is_superset_of b #=> true a.is_superset_of с #=> false
def is_a_superset_of(another_set) return false if another_set.size > self.size another_set.each do|element| return false unless self.has_element? element end return true end
Задания 37) Напишите метод #intersect_with, который бы принимал в качестве аргумента другое множество и возвращал новое множество, состоящее из элементов, общих для этих двух множеств. a = Set.new([1,hi,3,10]) c = Set.new([10, hi, 23]) a.intersect_with c #=>
def intersect_with(another_set) res = Set.new self.each do |e| res.add e if another_set.has_element? e end return res end def intersect_with(another_set) res = Set.new a, b = self, another_set if a.size > b.size # Оптимизация для очень a,b = b,a # больших множеств end a.each do |e| res.add e if b.has_element? e end return res end
Задания 38) Напишите метод +, который бы принимал в качестве аргумента другое множество и возвращал новое множество, состоящее из всех элементов обоих множеств. a = Set.new([1,hi,3,10]) с = Set.new([10, hi, 23]) a + c #=>
def +(another_set) res = self.dup another_set.each {|e| res.add e} return res end
Задания 39) Напишите метод -, который бы принимал в качестве аргумента другое множество и возвращал новое множество, состоящее из элементов текущего множества минус элементы, общие для обоих множеств. a = Set.new([1,hi,3,10]) с = Set.new([10, hi, 23]) a - c #=>
def -(another_set) res = Set.new self.each do |e| unless another_set.has_element? e res.add e end return res end