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

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

Към профила на Елена Иванова

Резултати

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

Код

class Song
attr_accessor :name, :artist, :genre, :subgenre, :tags
def initialize(name, artist, genre, subgenre, tags)
@name = name
@artist = artist
@genre = genre
@subgenre = subgenre
@tags = tags
end
def matches?(criteria)
if criteria == {}
return true
end
name = criteria.fetch(:name, "")
artist = criteria.fetch(:artist, "")
tags = criteria.fetch(:tags, [])
verify_value(@name, name) and
verify_value(@artist, artist) and
verify_tags(@tags, tags)
end
private
def verify_value(value, expected)
if expected == "" or value == expected
return true
end
false
end
def verify_tags(tags, expected)
if expected.kind_of?(String)
expected = Array(expected)
end
expected.each do |tag|
if tag.end_with?("!") and tags.include?(tag.chop)
return false
elsif not tag.end_with?("!") and not tags.include?(tag)
return false
end
end
true
end
end
class Collection
ArtistTags = {
'John Coltrane' => %w[saxophone],
'Bach' => %w[piano polyphony],
}
def initialize(songs_as_string, artist_tags = ArtistTags)
@collection = parse_songs(songs_as_string, artist_tags)
end
def find(criteria)
if criteria == {}
return @collection
end
matched = @collection.select {|song| song.matches? criteria}
p matched
block = criteria[:filter]
if block
block_arr = @collection.select {|song| block.(song)}
p block_arr
return matched & block_arr
end
matched
end
private
def parse_songs(songs_as_string, artist_tags)
songs_strings = songs_as_string.lines
songs_strings = songs_strings.map {|line| line.strip }
songs = songs_strings.map {|song| song_string_to_object(song)}
songs.each {|song| song.tags += artist_tags.fetch(song.artist, [])}
end
def song_string_to_object(song)
song_arr = song.split(%r{\.\s*})
name = song_arr[0].strip
artist = song_arr[1].strip
genres = song_arr[2]
tags = song_arr[3]
construct_song(name, artist, genres, tags)
end
def construct_song(song, artist, genres, tags)
separator = %r{,\s*}
genre = genres.split(separator)[0].strip
subgenre = genres.split(separator)[1]
tags = tags || ""
tags = tags.split(separator) + Array(genre.downcase)
if subgenre
subgenre.strip!
tags = tags + Array(subgenre.downcase)
end
Song.new(song, artist, genre, subgenre, tags)
end
end

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

.[#<Song:0xa6e9ec0 @name="Autumn Leaves", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>, #<Song:0xa6e9d08 @name="Waltz for Debbie", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["jazz"]>]
.[#<Song:0xa6f6ea4 @name="'Round Midnight", @artist="John Coltrane", @genre="Jazz", @subgenre=nil, @tags=["jazz", "saxophone"]>, #<Song:0xa662a60 @name="'Round Midnight", @artist="Thelonious Monk", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>]
.[#<Song:0xa66f4a4 @name="Miles Runs the Voodoo Down", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "jazz", "fusion"]>]
.[#<Song:0xa776460 @name="Toccata e Fuga", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["popular", "classical", "baroque", "piano", "polyphone"]>, #<Song:0xa7761f4 @name="Goldberg Variations", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["classical", "baroque", "piano", "polyphone"]>]
.[#<Song:0xa77ebd8 @name="Eine Kleine Nachtmusik", @artist="Mozart", @genre="Classical", @subgenre=nil, @tags=["popular", "violin", "classical"]>]
.[#<Song:0xa788098 @name="Miles Runs the Voodoo Down", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "jazz", "fusion"]>]
.[#<Song:0xa79291c @name="My Favourite Things", @artist="John Coltrane", @genre="Jazz", @subgenre="Bebop", @tags=["popular", "cover", "jazz", "bebop", "saxophone"]>, #<Song:0xa792660 @name="Greensleves", @artist="John Coltrane", @genre="Jazz", @subgenre="Bebop", @tags=["popular", "cover", "jazz", "bebop", "saxophone"]>, #<Song:0xa7923f4 @name="Alabama", @artist="John Coltrane", @genre="Jazz", @subgenre="Avantgarde", @tags=["melancholic", "jazz", "avantgarde", "saxophone"]>, #<Song:0xa792174 @name="Acknowledgement", @artist="John Coltrane", @genre="Jazz", @subgenre="Avantgarde", @tags=["jazz", "avantgarde", "saxophone"]>, #<Song:0xa791fa8 @name="Afro Blue", @artist="John Coltrane", @genre="Jazz", @subgenre=nil, @tags=["melancholic", "jazz", "saxophone"]>, #<Song:0xa791ddc @name="'Round Midnight", @artist="John Coltrane", @genre="Jazz", @subgenre=nil, @tags=["jazz", "saxophone"]>, #<Song:0xa791c10 @name="My Funny Valentine", @artist="Miles Davis", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>, #<Song:0xa79197c @name="Tutu", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "cool", "jazz", "fusion"]>, #<Song:0xa791710 @name="Miles Runs the Voodoo Down", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "jazz", "fusion"]>, #<Song:0xa7914b8 @name="Boplicity", @artist="Miles Davis", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>, #<Song:0xa7912ec @name="Autumn Leaves", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>, #<Song:0xa791134 @name="Waltz for Debbie", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["jazz"]>, #<Song:0xa790eb4 @name="'Round Midnight", @artist="Thelonious Monk", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>, #<Song:0xa790cd4 @name="Ruby, My Dear", @artist="Thelonious Monk", @genre="Jazz", @subgenre=nil, @tags=["saxophone", "jazz"]>, #<Song:0xa790b1c @name="Fur Elise", @artist="Beethoven", @genre="Classical", @subgenre=nil, @tags=["popular", "classical"]>, #<Song:0xa790950 @name="Moonlight Sonata", @artist="Beethoven", @genre="Classical", @subgenre=nil, @tags=["popular", "classical"]>, #<Song:0xa7907ac @name="Pathetique", @artist="Beethoven", @genre="Classical", @subgenre=nil, @tags=["classical"]>, #<Song:0xa790540 @name="Toccata e Fuga", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["popular", "classical", "baroque", "piano", "polyphone"]>, #<Song:0xa87e4d4 @name="Goldberg Variations", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["classical", "baroque", "piano", "polyphone"]>, #<Song:0xa87e2cc @name="Eine Kleine Nachtmusik", @artist="Mozart", @genre="Classical", @subgenre=nil, @tags=["popular", "violin", "classical"]>]
[#<Song:0xa7912ec @name="Autumn Leaves", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>]
.[#<Song:0xa88fc48 @name="Toccata e Fuga", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["popular", "classical", "baroque", "piano", "polyphone"]>, #<Song:0xa88f9dc @name="Goldberg Variations", @artist="Bach", @genre="Classical", @subgenre="Baroque", @tags=["classical", "baroque", "piano", "polyphone"]>]
.[#<Song:0xac26334 @name="'Round Midnight", @artist="Thelonious Monk", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>]
.[#<Song:0xac3143c @name="'Round Midnight", @artist="Thelonious Monk", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>]
[#<Song:0xac32ea4 @name="My Favourite Things", @artist="John Coltrane", @genre="Jazz", @subgenre="Bebop", @tags=["popular", "cover", "jazz", "bebop", "saxophone"]>, #<Song:0xac32be8 @name="Greensleves", @artist="John Coltrane", @genre="Jazz", @subgenre="Bebop", @tags=["popular", "cover", "jazz", "bebop", "saxophone"]>, #<Song:0xac3297c @name="Alabama", @artist="John Coltrane", @genre="Jazz", @subgenre="Avantgarde", @tags=["melancholic", "jazz", "avantgarde", "saxophone"]>, #<Song:0xac326fc @name="Acknowledgement", @artist="John Coltrane", @genre="Jazz", @subgenre="Avantgarde", @tags=["jazz", "avantgarde", "saxophone"]>, #<Song:0xac32530 @name="Afro Blue", @artist="John Coltrane", @genre="Jazz", @subgenre=nil, @tags=["melancholic", "jazz", "saxophone"]>, #<Song:0xac32364 @name="'Round Midnight", @artist="John Coltrane", @genre="Jazz", @subgenre=nil, @tags=["jazz", "saxophone"]>, #<Song:0xac32198 @name="My Funny Valentine", @artist="Miles Davis", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>, #<Song:0xac31f04 @name="Tutu", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "cool", "jazz", "fusion"]>, #<Song:0xac31c98 @name="Miles Runs the Voodoo Down", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "jazz", "fusion"]>, #<Song:0xac31a40 @name="Boplicity", @artist="Miles Davis", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>, #<Song:0xac31874 @name="Autumn Leaves", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["popular", "jazz"]>, #<Song:0xac316bc @name="Waltz for Debbie", @artist="Bill Evans", @genre="Jazz", @subgenre=nil, @tags=["jazz"]>, #<Song:0xac3143c @name="'Round Midnight", @artist="Thelonious Monk", @genre="Jazz", @subgenre="Bebop", @tags=["jazz", "bebop"]>, #<Song:0xac3125c @name="Ruby, My Dear", @artist="Thelonious Monk", @genre="Jazz", @subgenre=nil, @tags=["saxophone", "jazz"]>]
.[#<Song:0xac3ac94 @name="Tutu", @artist="Miles Davis", @genre="Jazz", @subgenre="Fusion", @tags=["weird", "cool", "jazz", "fusion"]>]
.

Finished in 0.54553 seconds
12 examples, 0 failures

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

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

+class Song
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+
+ def initialize(name, artist, genre, subgenre, tags)
+ @name = name
+ @artist = artist
+ @genre = genre
+ @subgenre = subgenre
+ @tags = tags
+ end
+
+ def matches?(criteria)
+ if criteria == {}
+ return true
+ end
+ name = criteria.fetch(:name, "")
+ artist = criteria.fetch(:artist, "")
+ tags = criteria.fetch(:tags, [])
+ verify_value(@name, name) and
+ verify_value(@artist, artist) and
+ verify_tags(@tags, tags)
+ end
+
+ private
+
+ def verify_value(value, expected)
+ if expected == "" or value == expected
+ return true
+ end
+ false
+ end
+
+ def verify_tags(tags, expected)
+ if expected.kind_of?(String)
+ expected = Array(expected)
+ end
+ expected.each do |tag|
+ if tag.end_with?("!") and tags.include?(tag.chop)
+ return false
+ elsif not tag.end_with?("!") and not tags.include?(tag)
+ return false
+ end
+ end
+ true
+ end
+end
+
+class Collection
+ ArtistTags = {
+ 'John Coltrane' => %w[saxophone],
+ 'Bach' => %w[piano polyphony],
+ }
+
+ def initialize(songs_as_string, artist_tags = ArtistTags)
+ @collection = parse_songs(songs_as_string, artist_tags)
+ end
+
+ def find(criteria)
+ if criteria == {}
+ return @collection
+ end
+ matched = @collection.select {|song| song.matches? criteria}
+ p matched
+ block = criteria[:filter]
+ if block
+ block_arr = @collection.select {|song| block.(song)}
+ p block_arr
+ return matched & block_arr
+ end
+ matched
+ end
+
+ private
+
+ def parse_songs(songs_as_string, artist_tags)
+ songs_strings = songs_as_string.lines
+ songs_strings = songs_strings.map {|line| line.strip }
+ songs = songs_strings.map {|song| song_string_to_object(song)}
+ songs.each {|song| song.tags += artist_tags.fetch(song.artist, [])}
+ end
+
+ def song_string_to_object(song)
+ song_arr = song.split(%r{\.\s*})
+ name = song_arr[0].strip
+ artist = song_arr[1].strip
+ genres = song_arr[2]
+ tags = song_arr[3]
+ construct_song(name, artist, genres, tags)
+ end
+
+ def construct_song(song, artist, genres, tags)
+ separator = %r{,\s*}
+ genre = genres.split(separator)[0].strip
+ subgenre = genres.split(separator)[1]
+ tags = tags || ""
+ tags = tags.split(separator) + Array(genre.downcase)
+ if subgenre
+ subgenre.strip!
+ tags = tags + Array(subgenre.downcase)
+ end
+ Song.new(song, artist, genre, subgenre, tags)
+ end
+end
  • Константата ArtistTags в Collection няма голям смисъл. Това е част от примерния ни тест, наистина, ама нали.
  • Не спазваш идентацията на две места - в ArtistTags и в construct_song. Протокола изисква да ти взема точка за това.
  • subgenre = subgenre.strip е по-добре от subgenre.strip!. Ако има друга референция към subgenre (това лесно се случва), вероятността за бъг ще е по-малка.
  • Слагат се скоби от вътрешната страна на блоковете - each { |x| foo(x) }, а не each {|x| foo(x)}.
  • Няма нужда да ползваш %r{\.\s*}. /\.\s*/ е по-подходящо (и по-кратко). %r се ползва само ако ти трябва \ в регулярния израз.
  • Имаш разхвърляни p-та из кода, което не е ОК.
  • Няма нужда да правиш expected = Array(expected) if expected.kind_of? String. Може просто Array(expected). Това му е идеята.
  • verify_value може да се сведе до точно един ред. Условието на if-а. Просто def verify_value(value, expected) expected == "" or value == expected end. Ще стане доста по-добре.
  • Във verify_tags си искала да ползваш all? или any?.

Между другото, скептика не може ли да проверява за нарушения на конвенцията? Би било полезно... случвало ми се е да се ровя из нета за това... случвало ми се е и да се подвеждам от примери в нета :(