Решение на Втора задача от Борис Минев

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

Към профила на Борис Минев

Резултати

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

Код

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

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

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

Finished in 0.54792 seconds
12 examples, 0 failures

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

Борис обнови решението на 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 реда (което е крайно грешен подход - просто исках да видя колко кратко може да стане :) ). После го редактирах за да отговаря на стиловите изисквания и се получи това горе. Грозният и странен код на места се дължи на това.

Благодаря ти за съветите. Ще се опитам в следващите домашни да не допускам такива грешки.