Димо обнови решението на 27.10.2011 14:00 (преди около 14 години)
+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?
