Решение на Втора задача от Велина Ташева

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

Към профила на Велина Ташева

Резултати

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

Код

class Collection
attr_accessor :songs
def initialize(songs_as_string, tags)
@songs = parse(songs_as_string)
tags.each do |key, value|
temp_songs = @songs.find_all { |s| s.artist = key }
temp_songs.each do |s|
s.tags << value
end
end
end
def parse(songs_as_string)
songs_to_return = Array.new
songs_as_string.lines("\n").each do |string|
string_parts = string.split(".")
current_song = Song.new
current_song = update_song(string_parts)
current_song.tags << current_song.genre.downcase
current_song.subgenre = string_parts[2].split(",")[1]
if (current_song.subgenre != nil)
current_song.subgenre = current_song.subgenre.strip
current_song.tags << current_song.subgenre.downcase
end
songs_to_return << current_song
end
songs_to_return
end
def update_song(string_parts)
current_song = Song.new
current_song.name = string_parts[0].strip
current_song.artist = string_parts[1].strip
current_song.tags = get_tags(string_parts[3])
current_song.genre = string_parts[2].split(",")[0].strip
current_song
end
def find(criteria)
@songs.find_all { |s| s.match?(criteria) }
end
def get_tags(part)
if part != nil
tags = part.split(",")
tags = tags.map { |t| t.strip }
else
tags = []
end
tags
end
end
class Song
attr_accessor :name
attr_accessor :artist
attr_accessor :genre
attr_accessor :subgenre
attr_accessor :tags
def match?(criteria)
if criteria[:name] != nil and name != criteria[:name]
return false
end
if criteria[:artist] != nil and artist != criteria[:artist]
return false
end
if criteria[:tags] != nil
tags_are_ok = check_tags(criteria[:tags])
if not tags_are_ok
return false
end
end
if criteria[:filter] != nil and not criteria[:filter].call(self)
return false
end
true
end
def check_tags(tags)
crit_tags = get_criteria_tags(tags)
tags_to_have, tags_not_to_have = split(crit_tags)
have_are_ok = tags_to_have.all? { |t| @tags.include?(t) }
not_have_are_ok = tags_not_to_have.all? { |t| not @tags.include?(t) }
have_are_ok && not_have_are_ok
end
def get_criteria_tags(tags)
crit_tags = Array.new
crit_tags << tags
crit_tags.flatten
end
def split(tags)
tags_to_have = tags.find_all { |t| not t=~ /!$/ }
tags_not_to_have = tags.find_all { |t| t=~ /!$/ }
tags_not_to_have = tags_not_to_have.map { |t| t.chomp('!') }
return tags_to_have, tags_not_to_have
end
end

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

.FF.....FFFF

Failures:

  1) Collection can look up songs by artist
     Failure/Error: songs(artist: 'Bill Evans').map(&:name).should =~ ['Autumn Leaves', 'Waltz for Debbie']
       expected collection contained:  ["Autumn Leaves", "Waltz for Debbie"]
       actual collection contained:    []
       the missing elements were:      ["Autumn Leaves", "Waltz for Debbie"]
     # /tmp/d20111115-13548-18ibctn/spec.rb:41: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 look up songs by name
     Failure/Error: songs(name: "'Round Midnight").map(&:artist).should =~ ['John Coltrane', 'Thelonious Monk']
       expected collection contained:  ["John Coltrane", "Thelonious Monk"]
       actual collection contained:    ["Bach", "Bach"]
       the missing elements were:      ["John Coltrane", "Thelonious Monk"]
       the extra elements were:        ["Bach", "Bach"]
     # /tmp/d20111115-13548-18ibctn/spec.rb:45: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 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-18ibctn/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)>'

  4) Collection allows multiple criteria
     Failure/Error: songs(name: "'Round Midnight", tags: 'bebop').map(&:artist).should eq ['Thelonious Monk']
       
       expected: ["Thelonious Monk"]
            got: ["Bach"]
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Thelonious Monk"]
       +["Bach"]
     # /tmp/d20111115-13548-18ibctn/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)>'

  5) 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-18ibctn/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)>'

  6) Collection constructs an object for each song
     Failure/Error: song.artist.should    eq 'Miles Davis'
       
       expected: "Miles Davis"
            got: "Bach"
       
       (compared using ==)
     # /tmp/d20111115-13548-18ibctn/spec.rb:89: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.56525 seconds
12 examples, 6 failures

Failed examples:

rspec /tmp/d20111115-13548-18ibctn/spec.rb:40 # Collection can look up songs by artist
rspec /tmp/d20111115-13548-18ibctn/spec.rb:44 # Collection can look up songs by name
rspec /tmp/d20111115-13548-18ibctn/spec.rb:68 # Collection adds the artist tags to the songs
rspec /tmp/d20111115-13548-18ibctn/spec.rb:72 # Collection allows multiple criteria
rspec /tmp/d20111115-13548-18ibctn/spec.rb:76 # Collection allows all criteria
rspec /tmp/d20111115-13548-18ibctn/spec.rb:85 # Collection constructs an object for each song

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

Велина обнови решението на 30.10.2011 12:15 (преди около 13 години)

+class Collection
+ attr_accessor :songs
+
+ def initialize(songs_as_string, tags)
+ @songs = parse(songs_as_string)
+
+ tags.each do |key, value|
+ temp_songs = @songs.find_all { |s| s.artist = key }
+ temp_songs.each do |s|
+ s.tags << value
+ end
+ end
+ end
+
+ def parse(songs_as_string)
+ songs_to_return = Array.new
+ songs_as_string.lines("\n").each do |string|
+ string_parts = string.split(".")
+ current_song = Song.new
+ current_song = update_song(string_parts)
+ current_song.tags << current_song.genre.downcase
+
+ current_song.subgenre = string_parts[2].split(",")[1]
+ if (current_song.subgenre != nil)
+ current_song.subgenre = current_song.subgenre.strip
+ current_song.tags << current_song.subgenre.downcase
+ end
+ songs_to_return << current_song
+ end
+ songs_to_return
+ end
+
+ def update_song(string_parts)
+ current_song = Song.new
+ current_song.name = string_parts[0].strip
+ current_song.artist = string_parts[1].strip
+ current_song.tags = get_tags(string_parts[3])
+ current_song.genre = string_parts[2].split(",")[0].strip
+ current_song
+ end
+
+ def find(criteria)
+ @songs.find_all { |s| s.match?(criteria) }
+ end
+
+ def get_tags(part)
+ if part != nil
+ tags = part.split(",")
+ tags = tags.map { |t| t.strip }
+ else
+ tags = []
+ end
+ tags
+ end
+end
+
+class Song
+ attr_accessor :name
+ attr_accessor :artist
+ attr_accessor :genre
+ attr_accessor :subgenre
+ attr_accessor :tags
+
+ def match?(criteria)
+ if criteria[:name] != nil and name != criteria[:name]
+ return false
+ end
+ if criteria[:artist] != nil and artist != criteria[:artist]
+ return false
+ end
+
+ if criteria[:tags] != nil
+ tags_are_ok = check_tags(criteria[:tags])
+
+ if not tags_are_ok
+ return false
+ end
+ end
+
+ if criteria[:filter] != nil and not criteria[:filter].call(self)
+ return false
+ end
+
+ true
+ end
+
+ def check_tags(tags)
+ crit_tags = get_criteria_tags(tags)
+ tags_to_have, tags_not_to_have = split(crit_tags)
+
+ have_are_ok = tags_to_have.all? { |t| @tags.include?(t) }
+ not_have_are_ok = tags_not_to_have.all? { |t| not @tags.include?(t) }
+ have_are_ok && not_have_are_ok
+ end
+
+ def get_criteria_tags(tags)
+ crit_tags = Array.new
+ crit_tags << tags
+ crit_tags.flatten
+ end
+
+ def split(tags)
+ tags_to_have = tags.find_all { |t| not t=~ /!$/ }
+
+ tags_not_to_have = tags.find_all { |t| t=~ /!$/ }
+ tags_not_to_have = tags_not_to_have.map { |t| t.chomp('!') }
+
+ return tags_to_have, tags_not_to_have
+ end
+end
  • Голяма част от методите ти могат да са private. Ако един метод се ползва само от същия клас, трябва да го направиш private. По този начин документираш това и позволяваш тези методи да бъдат променяни, по-лесно.
  • Никога, ама никога не се пише просто Array.new. Пише се [].
  • Няма нужда да слагаш скоби около условието на if-а.
  • Всичките ти attr_accessor-и могат да бъдат на един ред.
  • get_criteria_tags е невероятно странен. В него на практика правиш само tags.flatten. Не мога да разбера каква ти е била идеята.
  • Ако искаш да провериш дали низ завършва на удивителна, това най-ясно може да се запише като tag.end_with?('!').
  • В Collection#get_tags:
    • if part != nil се записва като if part.
    • Няма нужда от последните два tags =. По-долу има друг начин да го направиш. Разбира се, можеше просто да напишеш part ? part.split(',').map(&:strip) : [].
    • tags.map { |t| t.strip } се записва като tags.map(&:strip).
  • Enumerable#select е повече на почит от Enumerable#find_all. Не съм сигурен защо.
  • Имам малко забележки към имената:
    • tags_are_ok, tags_to_have, tags_not_to_have, not_have_are_ok, have_are_ok и прочее са странни имена. "have are ok and not have are ok" не се чете много добре. По-хубаво щеше да стане с "matches_including_tags and matches_excluding_tags".
    • crit_tags е странно съкратено име. "critical tags" или "criteria tags"?
    • Не мога да разбера защо променливата се казва temp_songs.
  • Вместо с return tags_to_have, tags_not_to_have можеше да завършиш с [tags_to_have, tags_not_to_have]. Двете правят едно и също.

Ето споменатия по-горе код:

def get_tags(part)
  if part
    part.split(',').map(&:strip)
  else
    []
  end
end