Борис обнови решението на 27.10.2011 00:24 (преди около 13 години)
+class Song
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre , *tags)
+ @name = name
+ @artist = artist
+ @genre = genre
+ @subgenre = subgenre
+ @tags = tags
+ end
+
+ def tags_matches?(tags)
+ tags = [*tags]
+ tags.select { |n| n[-1] != "!" }.all? { |n| @tags.include? n } &&
+ tags.select { |n| n[-1] == "!" }.none? { |n| @tags.include? n[0..-2] }
+ end
+
+ def name_matches?(name)
+ @name == name
+ end
+
+ def artist_matches?(artist)
+ @artist == artist
+ end
+
+ def filter_matches?(filter)
+ filter[self]
+ end
+
+ def matches?(criteria)
+ criteria.map { |key, value| self.send key.to_s + "_matches?", value }.all?
+ end
+end
+
+class Collection
+ attr_accessor :songs
+
+ def initialize(songs_as_string, artist_tags)
+ @songs = parse_song_list(songs_as_string, artist_tags)
+ end
+
+ def parse_song_list(songs_as_string, artist_tags)
+ lines = songs_as_string.split("\n")
+ song_str = lines.map { |n| n.split(".").map(&:strip) }
+ genre = parse_genre song_str
+ attr = parse_tags(genre)
+ songs = attr.map { |attributes| Song.new *attributes.flatten }
+ add_all_tags(songs, artist_tags)
+ end
+
+ def parse_genre(song_str)
+ genre = song_str.each do |n|
+ n[2] = n[2].split(",").map(&:strip)if n[2].include? ","
+ n[2] = [n[2]] << nil if !(n[2].include?",")
+ end
+ end
+
+ def parse_tags(song_str)
+ song_str.each do |n|
+ n[3] = n[3].split(",").map(&:strip) if !n[3].nil?
+ end
+ end
+
+ def add_all_tags(songs, artist_tags)
+ songs.each do |n|
+ n.tags |= (artist_tags[n.artist] || [])
+ n.tags |= [n.genre.downcase]
+ n.tags |= [n.subgenre||[]].flatten.map(&:downcase)
+ n.tags = n.tags.select { |n| !n.nil?}
+ end
+ end
+
+ def find(criteria = -1)
+ if criteria == -1
+ @songs
+ else
+ @songs.select { |song| song.matches? criteria }
+ end
+ end
+end
Мисля, че няма да мине тестовете :)
- Браво че си се сетил за
[*tags]
. Аз не се. -
tags_matches?
ми харесва, макар че може по-кратко. -
find(criteria = -1)
е странно. Трябваше да еfind(criteria = {})
. -
n
е много лошо име за текстов низ, песен или таг.genre
,song
иtag
щеше да е по-добре. - В
tags_matches?
третия ред трябва да е идентиран навътре. - Подхода ти на парсене е малко странен. По-точно това, че викаш
attributes.flatten
и това, чеparse_tags
иparse_genre
мутират аргумента си. Щеше да е по-хубаво да връщат резултат иparse_song_list
да го ползва. -
array.select { |n| !n.nil? }
може да се запише катоarray.compact
. Отделно,!n.nil?
е простоn
.
Давам в ти една бонус точка защото решението ти е кратко. Щях да ти дам пълните три, ако горните неща ги нямаше.
В първоначалния си вид домашното беше 15 реда (което е крайно грешен подход - просто исках да видя колко кратко може да стане :) ). После го редактирах за да отговаря на стиловите изисквания и се получи това горе. Грозният и странен код на места се дължи на това.
Благодаря ти за съветите. Ще се опитам в следващите домашни да не допускам такива грешки.