Димо обнови решението на 27.10.2011 14:00 (преди около 13 години)
+class Song
+
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize (name,artist,genre,subgenre,tags)
+ @name = name
+ @artist = artist
+ @genre = genre.strip
+ @subgenre = if subgenre == nil then nil else subgenre.strip end
+ @tags = Set.new(tags)
+ @tags.add @genre.downcase
+ if subgenre != nil
+ @tags.add @subgenre.downcase
+ end
+ end
+end
+class Collection
+ require 'set'
+
+ attr_accessor :songs
+
+ def initialize (songs_as_string, artist_tags)
+ @songs=[]
+ songs_as_string.each_line do |l|
+ tmp = l.split(%r{[\.]}).map{|n| n.strip}
+ if (tmp.size == 3)
+ @songs << Song.new(tmp[0],tmp[1],tmp[2].split(',')[0],tmp[2].split(',')[1],nil)
+ else
+ @songs << Song.new(tmp[0],tmp[1],tmp[2].split(',')[0],tmp[2].split(',')[1],tmp[3].split(',').map{|n| n.strip})
+ end
+ if(artist_tags.has_key? @songs[-1].artist)
+ @songs[-1].tags += artist_tags[@songs[-1].artist]
+ end
+ end
+ end
+
+ def find(criteria)
+ result = @songs
+ if criteria.has_key? :tags
+ taggs = if criteria[:tags].class == Array then criteria[:tags] else [criteria[:tags]] end
+ result = result.select{|song| (taggs.collect{|tag| if tag.end_with? '!' then not song.tags.include? tag.chomp('!') else song.tags.include? tag end}).all?}
+ end
+ if criteria.has_key? :name
+ result = result.select{|song| song.name == criteria[:name]}
+ end
+ if criteria.has_key? :artist
+ result = result.select{|song| song.artist == criteria[:artist]}
+ end
+ if criteria.has_key? :filter
+ result = result.select{|song| criteria[:filter].(song)}
+ end
+ result
+ end
+end
-
if criteria[:tags].class == Array
е отвратително. Можеш да ползвашcriteria[:tags].kind_of?
. Или да видиш какво правиArray('foo')
иArray(['foo', 'bar'])
. - Този
if then else end
е неприемлив. Или го разбий на няколко реда, или ползвай? :
- Защо между
initialize
и списъка му с параметри има интервал? -
songs_as_string.each_line
трябва да бъде#map
- Далеч по-просто ще е ако изместиш проверката дали песен отговаря на критерии в
Song
и сведешfind
до@songs.select { |song| song.satisfies? criteria }
Още коментари.
-
if subgenre == nil then nil else subgenre.strip end
е простоsubgenre && subgenre.strip
- Странни са ми тия
strip
-ове иdowncase
-и вSong
. По-добре стоят вCollection
. Клиента наSong
не би очаквал да му преформатираш параметрите. Ако го правиш, поне го прави със всички. -
.class == Array
още е тук и още ми е криво. -
require 'set'
трябва да бъде най-горе във файла. -
songs[-1]
се записва катоsongs.last
. - Следния ред може да накара бременна жена да пометне. Логически издържан е, но е форматирам лошо по много начини: result = result.select{|song| (taggs.collect{|tag| if tag.end_with? '!' then not song.tags.include? tag.chomp('!') else song.tags.include? tag end}).all?}
- Няма нужда от скобите около параметъра на
if
-а вif(artist_tags.has_key? @songs[-1].artist)
. -
taggs
? Защоtaggs
?