Виктория обнови решението на 29.10.2012 23:55 (преди около 12 години)
+class Criteria
+
+ attr_accessor :condition
+
+ def initialize (condition)
+ @condition = condition
+ end
+
+ def Criteria.name(song_name)
+ Criteria.new(lambda { |song| song.name == song_name })
+ end
+
+ def Criteria.artist(artist_name)
+ Criteria.new(lambda { |song| song.artist == artist_name })
+ end
+
+ def Criteria.album(album_name)
+ Criteria.new(lambda { |song| song.album == album_name })
+ end
+
+ def |(other)
+ Criteria.new(lambda { |song| condition or other.condition })
+ end
+
+ def &(other)
+ Criteria.new(lambda { |song| condition.(song) and other.condition.(song) })
+ end
+
+ def !
+ Criteria.new(lambda { |song| !condition.(song) })
+ end
+
+end
+
+class Collection
+
+ include Enumerable
+
+ attr_accessor :songs
+
+ def initialize(array_songs)
+ @songs = array_songs
+ end
+
+ def Collection.parse(text)
+ list = text.split("\n\n").map do |song|
+ name, artist, album = song.split("\n")[0..2]
+ Song.new(name, artist, album)
+ end
+ Collection.new(list)
+ end
+
+ def artists
+ map { |song| song.artist }.uniq
+ end
+
+ def albums
+ map { |song| song.album }.uniq
+ end
+
+ def names
+ map { |song| song.name }.uniq
+ end
+
+ def each
+ @songs.each { |elem| yield elem }
+ end
+
+ def filter (criteria)
+ Collection.new(select { |song| criteria.condition.(song) })
+ end
+
+ def adjoin (other_collection)
+ Collection.new(songs + other_collection.songs)
+ end
+
+end
+
+class Song
+
+ include Enumerable
+
+ attr_accessor :name, :artist, :album
+
+ def initialize(name, artist, album)
+ @name = name
+ @artist = artist
+ @album = album
+ end
+
+ def each
+ yield name
+ yield artist
+ yield album
+ end
+
+end
Добре, много хубаво. Няколко неща:
- Защо
Song
еEnumerable
? - Трите метода в
Collection
-artists
,names
иalbums
си приличат. Можеш ли да дефинираш четвърти, който да премахва повторението? - Опитай вместо да подаваш ламбда на
Criteria
да подаваш блок.