Решение на Втора задача от Аксения Пенкова

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

Към профила на Аксения Пенкова

Резултати

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

Код

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

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

....FFF.FFF.

Failures:

  1) Collection can find songs by tag
     Failure/Error: songs(tags: 'baroque').map(&:name).should =~ ['Toccata e Fuga', 'Goldberg Variations']
       expected collection contained:  ["Goldberg Variations", "Toccata e Fuga"]
       actual collection contained:    []
       the missing elements were:      ["Goldberg Variations", "Toccata e Fuga"]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:53:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Collection can find songs by multiple tags
     Failure/Error: songs(tags: %w[popular violin]).map(&:name).should eq ['Eine Kleine Nachtmusik']
       
       expected: ["Eine Kleine Nachtmusik"]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Eine Kleine Nachtmusik"]
       +[]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:57:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Collection can find songs that don't have a tag
     Failure/Error: songs(tags: %w[weird cool!]).map(&:name).should eq ['Miles Runs the Voodoo Down']
       
       expected: ["Miles Runs the Voodoo Down"]
            got: ["Tutu", "Miles Runs the Voodoo Down"]
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Miles Runs the Voodoo Down"]
       +["Tutu", "Miles Runs the Voodoo Down"]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:61:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Collection adds the artist tags to the songs
     Failure/Error: songs(tags: 'polyphone').map(&:name).should =~ ['Toccata e Fuga', 'Goldberg Variations']
       expected collection contained:  ["Goldberg Variations", "Toccata e Fuga"]
       actual collection contained:    []
       the missing elements were:      ["Goldberg Variations", "Toccata e Fuga"]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:69:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Collection allows multiple criteria
     Failure/Error: songs(name: "'Round Midnight", tags: 'bebop').map(&:artist).should eq ['Thelonious Monk']
       
       expected: ["Thelonious Monk"]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Thelonious Monk"]
       +[]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:73:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Collection allows all criteria
     Failure/Error: ).map(&:artist).should eq ['Thelonious Monk']
       
       expected: ["Thelonious Monk"]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Thelonious Monk"]
       +[]
     # /tmp/d20111115-13548-5y2h0j/spec.rb:82:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.55506 seconds
12 examples, 6 failures

Failed examples:

rspec /tmp/d20111115-13548-5y2h0j/spec.rb:52 # Collection can find songs by tag
rspec /tmp/d20111115-13548-5y2h0j/spec.rb:56 # Collection can find songs by multiple tags
rspec /tmp/d20111115-13548-5y2h0j/spec.rb:60 # Collection can find songs that don't have a tag
rspec /tmp/d20111115-13548-5y2h0j/spec.rb:68 # Collection adds the artist tags to the songs
rspec /tmp/d20111115-13548-5y2h0j/spec.rb:72 # Collection allows multiple criteria
rspec /tmp/d20111115-13548-5y2h0j/spec.rb:76 # Collection allows all criteria

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

Аксения обнови решението на 31.10.2011 16:55 (преди над 12 години)

+
+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

Особено когато продължава с 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 и кофти имена.