Решение на Втора задача от Димо Станев

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

Към профила на Димо Станев

Резултати

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

Код

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

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

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

Finished in 0.56937 seconds
12 examples, 0 failures

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

Димо обнови решението на 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?