Решение на Втора задача от Ивайло Христов

Обратно към всички решения

Към профила на Ивайло Христов

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 11 успешни тест(а)
  • 0 неуспешни тест(а)

Код

class Collection
include Enumerable
class Song
def self.parse(data)
new *data.split(/\n/m)
.map { |value| value.strip }
.select { |value| !value.empty? }
end
def initialize(name, artist, album)
@name = name
@artist = artist
@album = album
end
attr_accessor :name, :artist, :album
end
def initialize(songs_list)
@songs_list = songs_list.uniq
end
def self.parse(data)
songs = data.split(/\n\s*\n/).uniq.map do |song_data|
Song.parse song_data
end
new songs
end
def each
@songs_list.each do |song|
yield song
end
end
def names
@songs_list.map { |song| song.name }.uniq
end
def artists
@songs_list.map { |song| song.artist }.uniq
end
def albums
@songs_list.map { |song| song.album }.uniq
end
def adjoin(colection)
Collection.new @songs_list + colection.songs_list
end
def filter(condition)
Collection.new @songs_list.select &condition.condition
end
attr_reader :songs_list
end
class Criteria
def initialize(&block)
@condition = block
end
def self.artist(artist_name)
new { |song| song.artist == artist_name }
end
def self.album(album_title)
new { |song| song.album == album_title }
end
def self.name(song_name)
new { |song| song.name == song_name }
end
def |(joined_criteria)
Criteria.new do |song|
self.condition.call(song) or joined_criteria.condition.call(song)
end
end
def &(joined_criteria)
Criteria.new do |song|
self.condition.call(song) and joined_criteria.condition.call(song)
end
end
def !
Criteria.new do |song|
!self.condition.call(song)
end
end
attr_reader :condition
end

Лог от изпълнението

...........

Finished in 0.01325 seconds
11 examples, 0 failures

История (3 версии и 3 коментара)

Ивайло обнови решението на 27.10.2012 18:17 (преди над 11 години)

+class Collection < Array
+ class Song < Hash
+ FIELDS = [:name, :artist, :album]
+
+ def self.parse(data)
+ Song.new *data.split(/\n/m)
+ .map { |value| value.strip }
+ .select { |value| !value.empty? }
+ end
+
+ def self.add_field_getter(name)
+ define_method(name) { self[name] }
+ end
+
+ def initialize(*data)
+ data.each_with_index do |value, index|
+ self[FIELDS[index]] = value
+ end
+ end
+
+ FIELDS.each do |field_name|
+ add_field_getter field_name
+ end
+
+ private_class_method :add_field_getter
+ end
+
+ def self.parse(data)
+ list = data.split(/\n\s*\n/).uniq.map do |song_data|
+ Song.parse song_data
+ end
+
+ new.push *list
+ end
+
+ def self.add_field_getter(name)
+ songs_mapper = lambda { |song| song[name] }
+
+ define_method(name) do
+ map(&songs_mapper).uniq
+ end
+ end
+
+ def adjoin(colection)
+ Collection.new.push *(self + colection)
+ end
+
+ def filter(condition)
+ Collection.new.push *(select &condition)
+ end
+
+ Song::FIELDS.each do |field_name|
+ add_field_getter field_name.to_s + 's'
+ end
+
+ private_class_method :add_field_getter
+end
+
+class Criteria < Proc
+ # ... due to thе Skeptic restrictions
+ def self.artist(artist_name)
+ new { |song| song[:artist] == artist_name }
+ end
+
+ def self.album(album_title)
+ new { |song| song[:album] == album_title }
+ end
+
+ def self.name(song_name)
+ new { |song| song[:name] == song_name }
+ end
+
+ def |(joined_criteria)
+ Criteria.new do |song|
+ self.call(song) or joined_criteria.call(song)
+ end
+ end
+ def &(joined_criteria)
+ Criteria.new do |song|
+ self.call(song) and joined_criteria.call(song)
+ end
+ end
+ def !
+ Criteria.new do |song|
+ !self.call(song)
+ end
+ end
+end

Ивайло обнови решението на 27.10.2012 18:34 (преди над 11 години)

class Collection < Array
class Song < Hash
FIELDS = [:name, :artist, :album]
def self.parse(data)
- Song.new *data.split(/\n/m)
+ new *data.split(/\n/m)
.map { |value| value.strip }
.select { |value| !value.empty? }
end
def self.add_field_getter(name)
define_method(name) { self[name] }
end
def initialize(*data)
data.each_with_index do |value, index|
self[FIELDS[index]] = value
end
end
FIELDS.each do |field_name|
add_field_getter field_name
end
private_class_method :add_field_getter
end
def self.parse(data)
list = data.split(/\n\s*\n/).uniq.map do |song_data|
Song.parse song_data
end
new.push *list
end
def self.add_field_getter(name)
songs_mapper = lambda { |song| song[name] }
- define_method(name) do
+ define_method(name.to_s + 's') do
map(&songs_mapper).uniq
end
end
def adjoin(colection)
Collection.new.push *(self + colection)
end
def filter(condition)
Collection.new.push *(select &condition)
end
Song::FIELDS.each do |field_name|
- add_field_getter field_name.to_s + 's'
+ add_field_getter field_name
end
private_class_method :add_field_getter
end
class Criteria < Proc
# ... due to thе Skeptic restrictions
def self.artist(artist_name)
new { |song| song[:artist] == artist_name }
end
def self.album(album_title)
new { |song| song[:album] == album_title }
end
def self.name(song_name)
new { |song| song[:name] == song_name }
end
def |(joined_criteria)
Criteria.new do |song|
self.call(song) or joined_criteria.call(song)
end
end
def &(joined_criteria)
Criteria.new do |song|
self.call(song) and joined_criteria.call(song)
end
end
def !
Criteria.new do |song|
!self.call(song)
end
end
end

Използваш наследяване по много грешен начин. Това определено ще ти струва точки. Искам да напомня, че на лекции споменахме да използвате композиция, а не наследяване. Сега няма да ти давам обяснение, защото мисля да направя едно по-подробно в понеделник или сряда.

Все пак - разкарай наследяването и го направи с композиция.

Ивайло обнови решението на 27.10.2012 21:04 (преди над 11 години)

-class Collection < Array
- class Song < Hash
- FIELDS = [:name, :artist, :album]
+class Collection
+ include Enumerable
+ class Song
def self.parse(data)
new *data.split(/\n/m)
.map { |value| value.strip }
.select { |value| !value.empty? }
end
- def self.add_field_getter(name)
- define_method(name) { self[name] }
+ def initialize(name, artist, album)
+ @name = name
+ @artist = artist
+ @album = album
end
- def initialize(*data)
- data.each_with_index do |value, index|
- self[FIELDS[index]] = value
- end
- end
+ attr_accessor :name, :artist, :album
+ end
- FIELDS.each do |field_name|
- add_field_getter field_name
- end
-
- private_class_method :add_field_getter
+ def initialize(songs_list)
+ @songs_list = songs_list.uniq
end
def self.parse(data)
- list = data.split(/\n\s*\n/).uniq.map do |song_data|
+ songs = data.split(/\n\s*\n/).uniq.map do |song_data|
Song.parse song_data
end
- new.push *list
+ new songs
end
- def self.add_field_getter(name)
- songs_mapper = lambda { |song| song[name] }
-
- define_method(name.to_s + 's') do
- map(&songs_mapper).uniq
+ def each
+ @songs_list.each do |song|
+ yield song
end
end
+ def names
+ @songs_list.map { |song| song.name }.uniq
+ end
+ def artists
+ @songs_list.map { |song| song.artist }.uniq
+ end
+ def albums
+ @songs_list.map { |song| song.album }.uniq
+ end
+
def adjoin(colection)
- Collection.new.push *(self + colection)
+ Collection.new @songs_list + colection.songs_list
end
def filter(condition)
- Collection.new.push *(select &condition)
+ Collection.new @songs_list.select &condition.condition
end
- Song::FIELDS.each do |field_name|
- add_field_getter field_name
- end
-
- private_class_method :add_field_getter
+ attr_reader :songs_list
end
-class Criteria < Proc
- # ... due to thе Skeptic restrictions
+class Criteria
+ def initialize(&block)
+ @condition = block
+ end
+
def self.artist(artist_name)
- new { |song| song[:artist] == artist_name }
+ new { |song| song.artist == artist_name }
end
def self.album(album_title)
- new { |song| song[:album] == album_title }
+ new { |song| song.album == album_title }
end
def self.name(song_name)
- new { |song| song[:name] == song_name }
+ new { |song| song.name == song_name }
end
def |(joined_criteria)
Criteria.new do |song|
- self.call(song) or joined_criteria.call(song)
+ self.condition.call(song) or joined_criteria.condition.call(song)
end
end
+
def &(joined_criteria)
Criteria.new do |song|
- self.call(song) and joined_criteria.call(song)
+ self.condition.call(song) and joined_criteria.condition.call(song)
end
end
+
def !
Criteria.new do |song|
- !self.call(song)
+ !self.condition.call(song)
end
end
+
+ attr_reader :condition
end

Варианта с наследяването беше с експериментална цел и що годе да си поиграя с динамиката на езика, без претанции за спазването на каквито и да било приниципи в OOP. Сметнах, че е интересен начин за решаване на текущата задача. Очаквам да се видя в OOP anti-patterns слайдовете. :))

Експеримента е валидна причина. Нещо, което можеш да напарвиш е да отвориш тема във форумите по този въпрос. Ще се радвам да ти отговаря нещо по-подробно там (където има повече видимост).

След крайния срок можеш да споделиш решението си във форумите и да го дискутираме.