Велина обнови решението на 30.10.2011 12:15 (преди около 13 години)
+class Collection
+ attr_accessor :songs
+
+ def initialize(songs_as_string, tags)
+ @songs = parse(songs_as_string)
+
+ tags.each do |key, value|
+ temp_songs = @songs.find_all { |s| s.artist = key }
+ temp_songs.each do |s|
+ s.tags << value
+ end
+ end
+ end
+
+ def parse(songs_as_string)
+ songs_to_return = Array.new
+ songs_as_string.lines("\n").each do |string|
+ string_parts = string.split(".")
+ current_song = Song.new
+ current_song = update_song(string_parts)
+ current_song.tags << current_song.genre.downcase
+
+ current_song.subgenre = string_parts[2].split(",")[1]
+ if (current_song.subgenre != nil)
+ current_song.subgenre = current_song.subgenre.strip
+ current_song.tags << current_song.subgenre.downcase
+ end
+ songs_to_return << current_song
+ end
+ songs_to_return
+ end
+
+ def update_song(string_parts)
+ current_song = Song.new
+ current_song.name = string_parts[0].strip
+ current_song.artist = string_parts[1].strip
+ current_song.tags = get_tags(string_parts[3])
+ current_song.genre = string_parts[2].split(",")[0].strip
+ current_song
+ end
+
+ def find(criteria)
+ @songs.find_all { |s| s.match?(criteria) }
+ end
+
+ def get_tags(part)
+ if part != nil
+ tags = part.split(",")
+ tags = tags.map { |t| t.strip }
+ else
+ tags = []
+ end
+ tags
+ end
+end
+
+class Song
+ attr_accessor :name
+ attr_accessor :artist
+ attr_accessor :genre
+ attr_accessor :subgenre
+ attr_accessor :tags
+
+ def match?(criteria)
+ if criteria[:name] != nil and name != criteria[:name]
+ return false
+ end
+ if criteria[:artist] != nil and artist != criteria[:artist]
+ return false
+ end
+
+ if criteria[:tags] != nil
+ tags_are_ok = check_tags(criteria[:tags])
+
+ if not tags_are_ok
+ return false
+ end
+ end
+
+ if criteria[:filter] != nil and not criteria[:filter].call(self)
+ return false
+ end
+
+ true
+ end
+
+ def check_tags(tags)
+ crit_tags = get_criteria_tags(tags)
+ tags_to_have, tags_not_to_have = split(crit_tags)
+
+ have_are_ok = tags_to_have.all? { |t| @tags.include?(t) }
+ not_have_are_ok = tags_not_to_have.all? { |t| not @tags.include?(t) }
+ have_are_ok && not_have_are_ok
+ end
+
+ def get_criteria_tags(tags)
+ crit_tags = Array.new
+ crit_tags << tags
+ crit_tags.flatten
+ end
+
+ def split(tags)
+ tags_to_have = tags.find_all { |t| not t=~ /!$/ }
+
+ tags_not_to_have = tags.find_all { |t| t=~ /!$/ }
+ tags_not_to_have = tags_not_to_have.map { |t| t.chomp('!') }
+
+ return tags_to_have, tags_not_to_have
+ end
+end
- Голяма част от методите ти могат да са
private
. Ако един метод се ползва само от същия клас, трябва да го направишprivate
. По този начин документираш това и позволяваш тези методи да бъдат променяни, по-лесно. - Никога, ама никога не се пише просто
Array.new
. Пише се[]
. - Няма нужда да слагаш скоби около условието на
if
-а. - Всичките ти
attr_accessor
-и могат да бъдат на един ред. -
get_criteria_tags
е невероятно странен. В него на практика правиш самоtags.flatten
. Не мога да разбера каква ти е била идеята. - Ако искаш да провериш дали низ завършва на удивителна, това най-ясно може да се запише като
tag.end_with?('!')
. - В
Collection#get_tags
:-
if part != nil
се записва катоif part
. - Няма нужда от последните два
tags =
. По-долу има друг начин да го направиш. Разбира се, можеше просто да напишешpart ? part.split(',').map(&:strip) : []
. -
tags.map { |t| t.strip }
се записва катоtags.map(&:strip)
.
-
-
Enumerable#select
е повече на почит отEnumerable#find_all
. Не съм сигурен защо. - Имам малко забележки към имената:
-
tags_are_ok
,tags_to_have
,tags_not_to_have
,not_have_are_ok
,have_are_ok
и прочее са странни имена. "have are ok and not have are ok" не се чете много добре. По-хубаво щеше да стане с "matches_including_tags and matches_excluding_tags". -
crit_tags
е странно съкратено име. "critical tags" или "criteria tags"? - Не мога да разбера защо променливата се казва
temp_songs
.
-
- Вместо с
return tags_to_have, tags_not_to_have
можеше да завършиш с[tags_to_have, tags_not_to_have]
. Двете правят едно и също.
Ето споменатия по-горе код:
def get_tags(part)
if part
part.split(',').map(&:strip)
else
[]
end
end