Аксения обнови решението на 31.10.2011 16:55 (преди около 13 години)
+
+class Song
+ attr_reader :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre=nil, tags=[])
+ @name, @artist = name, artist
+ @genre, @subgenre = genre, subgenre
+ @tags = tags
+ end
+
+ def add_genre_tags
+ tags << genre.downcase
+ tags << subgenre.downcase if subgenre
+ end
+
+end
+
+class Collection
+ attr_reader :catalog
+
+ def initialize(catalog, artist_tags)
+ @catalog = []
+ catalog.lines do |line|
+ song = Song.new(*parse(line))
+ song.add_genre_tags
+ @catalog << song
+ @artist_tags = artist_tags
+ # add_artist_tags
+ end
+ end
+
+ def add_artist_tags
+ @artist_tags.each do |artist, tag|
+ @catalog.each do |song|
+ if song.artist == artist
+ song.tags << tag
+ song.tags.flatten!
+ end
+ end
+ end
+ end
+
+ def find(criteria={})
+ res = Marshal.load(Marshal.dump @catalog)
+
+ res.select! { |song| song.name == criteria[:name] } \
+ if criteria.has_key? :name
+
+ res.select! { |song| song.artist == criteria[:artist] } \
+ if criteria.has_key? :artist
+
+ if criteria.has_key? :tags
+ contains, not_contains = group_tags criteria[:tags]
+ res.select! { |song| contains.all? { |tag| song.tags.include? tag } }
+
+ res.reject! { |song| not_contains.all? { |tag| song.tags.include? tag } }
+ end
+
+ res.select! { |song| criteria[:filter].call(song) } \
+ if criteria.has_key? :filter
+ res
+ end
+
+ private
+ def group_tags(tags)
+ tags = Array(tags) unless tags.kind_of? Array
+ not_contains = tags.select { |tag| tag.include? "!" }
+ contains = tags - not_contains
+
+ [contains, not_contains]
+ end
+
+ def parse(input)
+ data = input.split('.').map(&:strip)
+ data[2] = \
+ data[2].include?(',') ? data[2].split(',').map(&:strip) : [data[2], nil]
+ data.flatten!
+ if data.size == 5
+ data[4] = \
+ data[4].include?(',') ? data[4].split(',').map(&:strip) : [data[4]]
+ end
+ data
+ end
+end
ВТФ, ще кажа на Дени, че ползваш \
за line continuation :) Наистина, страшно странно изглежда.
Особено когато продължава с if
. Следните сегменти в кода ти са ми бая объркващи.
data[4] = \
data[4].include?(',') ? data[4].split(',').map(&:strip) : [data[4]]
Или пък:
res.select! { |song| song.artist == criteria[:artist] } \
if criteria.has_key? :artist
Аз бих ги събрал на един ред.
Разбира се, има стилови ограничения, затова:
if criteria.has_key? :artist
res.select! { |song| song.artist == criteria[:artist] }
end
Просто исках да приглася на Митьо. Ще напиша един (доста) по-дълъг списък по-натам.
Ъ, нямам никаква идея от къде се е взело това data[4] = \
(и двата реда), честно.
А иначе много, ама много ме е срам от това домашно... :( (даже не работи особенно) и "\" му е най-малкият проблем. И аз бих го събрала на един ред, ама ц, и това беше по-малкото зло от гаден witespace и кофти имена.