Решение на Втора задача от Деница Генчева

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

Към профила на Деница Генчева

Резултати

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

Код

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

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

............

Finished in 0.55271 seconds
12 examples, 0 failures

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

Деница обнови решението на 30.10.2011 15:09 (преди над 12 години)

+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 = {}).

Отвъд тези неща, решението ти е доста добро. Кратко, ясно и добра изолация между парсене и проверка на критериите. Печелиш бонус точка за това.

Следващия път да вдигнеш ръка в час :)