Габриела обнови решението на 25.10.2014 10:43 (преди около 10 години)
+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?
много си приличат. Кои два от тях можеш да махнеш без нещата да се счупят? :))