Габриела обнови решението на 25.10.2014 10:43 (преди около 11 години)
+class NumberSet
+ include Enumerable
+
+ attr_accessor :numbers
+
+ def initialize
+ @numbers = []
+ end
+
+ def each(&block)
+ @numbers.each(&block)
+ end
+
+ def <<(element)
+ @numbers << element unless @numbers.include?(element)
+ end
+
+ def size
+ @numbers.size
+ end
+
+ def empty?
+ return true if @numbers.size == 0
+ false
+ end
+
+ def [](filter)
+ filtered_numbers = NumberSet.new
+ array = @numbers.select { |number| filter.matches? number }
+ array.each { |number| numbers << number }
+ filtered_numbers
+ end
+end
+
+class Filter
+ attr_accessor :filter
+
+ def initialize(&block)
+ @filter = block
+ end
+
+ def matches?(numbers)
+ @filter.(numbers)
+ end
+
+ def |(filter)
+ Filter.new { |number| matches? number or filter.matches? number }
+ end
+
+ def &(filter)
+ Filter.new { |number| matches? number and filter.matches? number }
+ end
+end
+
+class TypeFilter < Filter
+ attr_accessor :filter
+
+ def initialize(type)
+ if type == :integer
+ @filter = lambda { |number| number.is_a? Integer }
+ elsif type == :real
+ @filter = lambda { |number| number.is_a? Rational or number.is_a? Float}
+ else
+ @filter = lambda { |number| number.is_a? Complex }
+ end
+ end
+
+ def matches?(numbers)
+ @filter.(numbers)
+ end
+end
+
+class SignFilter < Filter
+ attr_accessor :filter
+
+ def initialize(sign)
+ @filter = lambda { |number| number > 0 } if sign == :positive
+ @filter = lambda { |number| number <= 0 } if sign == :non_positive
+ @filter = lambda { |number| number < 0 } if sign == :negative
+ @filter = lambda { |number| number >= 0 } if sign == :non_negative
+ end
+
+ def matches?(numbers)
+ @filter.(numbers)
+ end
+end
Здрасти,
Ето няколко неща, върху които можеш да помислиш:
- Защо параметъра на
NumberSet#<<се казваelementпри положение, че навсякъде си ползвала по-яснотоnumber? -
attr_accessor-ите не са ти нужни. -
return true if @numbers.size == 0; falseе еквивалентно на@numbers.size == 0, което е еквивалентно на@numbers.empty?. Кой според теб е по-четимия вариант от трите? :) - Имаш typo в
NumberSet#[].filtered_numbersседи празен. Можеш да погледнешEnumerable#each_with_object. -
TypeFilterнаследяваFilter. Можеш да се възползваш от това и да напишешsuper() { |number| number.is_a? Integer }. Това ще подаде блок на конструктора наFilterи ще има същия ефект. Също така можеш да пробвашcaseвместоif/elsif/else. Същите неща важат заSignFilter. -
Filter#matches?,TypeFIlter#matches?иSignFilter#matches?много си приличат. Кои два от тях можеш да махнеш без нещата да се счупят? :))
