Деница обнови решението на 30.10.2011 15:09 (преди около 13 години)
+class Song
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre=nil, tags=[])
+ @name = name
+ @artist = artist
+ @genre = genre
+ @subgenre = subgenre
+ @tags = tags
+ end
+
+ def matches?(criteria)
+ if (criteria[:name] != nil) and (check_name(criteria[:name]) == false)
+ return false
+ end
+ if (criteria[:artist] != nil) and (check_artist(criteria[:artist]) == false)
+ return false
+ end
+ if (criteria[:tags] != nil) and (check_tags(criteria[:tags]) == false)
+ return false
+ end
+ if (criteria[:filter] != nil) and (check_filter(criteria[:filter]) == false)
+ return false
+ end
+ true
+ end
+
+ def check_name(name)
+ @name.eql?(name)
+ end
+
+ def check_artist(artist)
+ @artist.eql?(artist)
+ end
+
+ def check_tags(tags)
+ if (tags.kind_of?(String))
+ check_tag(tags)
+ else
+ tags.all? {|tag| check_tag(tag)}
+ end
+ end
+
+ def check_tag(tag)
+ if tag.end_with?('!')
+ real_tag = tag[0, tag.length - 1]
+ not @tags.include?(real_tag)
+ else
+ @tags.include?(tag)
+ end
+ end
+
+ def check_filter(filter)
+ filter.call(self)
+ end
+end
+
+class Collection
+
+ attr_accessor :songs
+
+ def initialize(songs_as_string, artist_tags)
+ @songs = songs_as_string.lines.map {|line| create_song(line, artist_tags)}
+ end
+
+ def create_song(song_as_string, artist_tags_hash)
+ song = parse_song_string(song_as_string)
+
+ song.tags << song.genre.downcase
+ song.tags << song.subgenre.downcase if song.subgenre != nil
+
+ artist_tags = artist_tags_hash[song.artist]
+
+ genre_tags = [song.genre, song.subgenre]
+ song.tags = song.tags | artist_tags if artist_tags != nil
+
+ song
+ end
+
+ def parse_song_string(song_as_string)
+ song_attributes = song_as_string.split(".")
+
+ name = song_attributes[0].strip
+ artist = song_attributes[1].strip
+
+ genres = song_attributes[2].strip.split(",")
+ genre = genres[0].strip
+ subgenre = genres[1].strip if genres[1] != nil
+
+ if song_attributes[3]
+ tags = song_attributes[3].split(", ").map {|t| t.strip}
+ else
+ tags = []
+ end
+
+ Song.new(name,artist, genre, subgenre, tags)
+ end
+
+ def find(criteria={})
+ @songs.select { |song| song.matches?(criteria)}
+ end
+
+end
- Тук не си искала да викаш
.eql?
, а просто да ползваш==
. - Скобите околоко условието на
if
-а вcheck_tags
не са нужни. Нито тези около параметрите наkind_of?
. - Интервалите се слагат така:
map { |line| create_song(line, artist_tags) }
. - В
parse_song_string
можешда извадиш
tags =извън
if-а и да стане:
tags = if song_attributes[3]`. - В
Song#matches?
можеш да направиш простоif criteria[:name] and not check_name(criteria[:name])
. Така израза ще е по-прост. Мисля, че на лекцията в понеделник (на която не вдигна ръка :) ) показах друг начин да запишеш целия блок. - Между параметъра и стойността по подразбиране се оставят интервали:
def find(criteria = {})
.
Отвъд тези неща, решението ти е доста добро. Кратко, ясно и добра изолация между парсене и проверка на критериите. Печелиш бонус точка за това.
Следващия път да вдигнеш ръка в час :)