Теодор обнови решението на 31.10.2012 04:11 (преди около 12 години)
+class Collection
+ attr_reader :tracks_container
+
+ include Enumerable
+
+ def initialize(array = [])
+ @tracks_container = array
+ end
+
+ def self.parse(collection_file)
+ Collection.new((collection_file.split(/\n/).each_slice(4))
+ .each_with_object([]) { |track, result| result << Track.new(track) })
+ end
+
+ def artists
+ @tracks_container.map { |track| track.artist }.uniq
+ end
+
+ def albums
+ @tracks_container.map { |track| track.album }.uniq
+ end
+
+ def names
+ @tracks_container.map { |track| track.name }.uniq
+ end
+
+ def each
+ @tracks_container.each { |track| yield track }
+ end
+
+ def filter(criteria)
+ Collection.new(@tracks_container.select(&criteria.predicate))
+ end
+
+ def adjoin(other)
+ Collection.new(@tracks_container | other.tracks_container)
+ end
+end
+
+class Track
+ attr_reader :artist, :album, :name
+
+ def initialize(track_array)
+ @name, @artist, @album = track_array
+ end
+end
+
+class Criteria
+ attr_accessor :predicate
+
+ def initialize(filter_rule)
+ @predicate = filter_rule
+ end
+
+ def |(other)
+ Criteria.new(->(track) { @predicate.(track) | other.predicate.(track) })
+ end
+
+ def &(other)
+ Criteria.new(->(track) { @predicate.(track) & other.predicate.(track) })
+ end
+
+ def !
+ Criteria.new(->(track) { !predicate.(track) })
+ end
+
+ def self.name(name_value)
+ Criteria.new(->(track) { track.name == name_value })
+ end
+
+ def self.artist(artist_value)
+ Criteria.new(->(track) { track.artist == artist_value })
+ end
+
+ def self.album(album_value)
+ Criteria.new(->(track) { track.album == album_value })
+ end
+end