Решение на Втора задача от Георги Бойваленков

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

Към профила на Георги Бойваленков

Резултати

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

Код

class Song
def initialize(_name, _artist, _genre, _subgenre, _tags)
@name = _name
@artist = _artist
@genre = _genre
@subgenre = _subgenre
@tags = _tags
end
def name
@name
end
def artist
@artist
end
def genre
@genre
end
def subgenre
@subgenre
end
def tags
(@tags == []) ? nil : @tags
end
def add_tags(tag_list)
@tags += tag_list
end
def satisfies_tags(tag_list)
has_them = true
y = lambda {|s| @tags.index(s) != nil}
n = lambda {|s| @tags.index(s) == nil}
p = lambda {|e| e[-1] == '!' ? n.call(e[0, e.length - 1]) : y.call(e)}
tag_list.each do |tag|
has_them = has_them && p.call(tag)
end
has_them
end
def satisfy_single(field, value)
if field == :tags and value.kind_of? String
value = value.split(',').map {|x| x.lstrip}
end
case field
when :name then (@name == value)
when :artist then (@artist == value)
when :filter then value.call(self)
when :tags then satisfies_tags(value)
end
end
def satisfy_all(criteria)
isgood = true
criteria.each do |k, v|
isgood = isgood && satisfy_single(k, v)
end
isgood
end
end
class Collection
def add_entry(entry)
es = entry.split('.').map {|v| v.gsub("\n", "")}
name, artist = es[0].lstrip, es[1].lstrip
genre = (es[2].split(',')[0]).lstrip
sub = (es[2].split(',')[1] == nil) ? nil : (es[2].split(',')[1]).lstrip
tags = (sub == nil ? [] : [sub.downcase])
if es[3] != nil
tags = tags + es[3].lstrip.split(',')
end
tags.map {|v| v.lstrip!}
@entries << Song.new(name, artist, genre, sub, tags + [genre.downcase])
end
def add_tags(entry, adds)
if adds[entry.artist] != nil
entry.add_tags(adds[entry.artist])
end
end
def initialize(data, adds)
@entries = []
data.each_line do |entry|
add_entry(entry)
end
@entries.each do |entry|
add_tags(entry, adds)
end
end
def get_songs
@entries
end
def find(criteria)
res = []
@entries.each do |song|
if song.satisfy_all(criteria)
res << song
end
end
res
end
end

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

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

Finished in 0.55009 seconds
12 examples, 0 failures

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

Георги обнови решението на 28.10.2011 12:42 (преди над 12 години)

+class Song
+
+ def initialize(_name, _artist, _genre, _subgenre, _tags)
+ @name = _name
+ @artist = _artist
+ @genre = _genre
+ @subgenre = _subgenre
+ @tags = _tags
+ end
+
+ def name
+ @name
+ end
+ def artist
+ @artist
+ end
+ def genre
+ @genre
+ end
+ def subgenre
+ @subgenre
+ end
+ def tags
+ (@tags == []) ? nil : @tags
+ end
+
+ def add_tags(tag_list)
+ @tags += tag_list
+ end
+ def satisfies_tags(tag_list)
+ has_them = true
+ y = lambda {|s| @tags.index(s) != nil}
+ n = lambda {|s| @tags.index(s) == nil}
+ p = lambda {|e| e[-1] == '!' ? n.call(e[0, e.length - 1]) : y.call(e)}
+ tag_list.each do |tag|
+ has_them = has_them && p.call(tag)
+ end
+ has_them
+ end
+
+ def satisfy_single(field, value)
+ if field == :tags and value.kind_of? String
+ value = value.split(',').map {|x| x.lstrip}
+ end
+ case field
+ when :name then (@name == value)
+ when :artist then (@artist == value)
+ when :filter then value.call(self)
+ when :tags then satisfies_tags(value)
+ end
+ end
+ def satisfy_all(criteria)
+ isgood = true
+ criteria.each do |k, v|
+ isgood = isgood && satisfy_single(k, v)
+ end
+ isgood
+ end
+end
+
+class Collection
+
+ def add_entry(entry)
+ es = entry.split('.').map {|v| v.gsub("\n", "")}
+ name, artist = es[0].lstrip, es[1].lstrip
+ genre = (es[2].split(',')[0]).lstrip
+ sub = (es[2].split(',')[1] == nil) ? nil : (es[2].split(',')[1]).lstrip
+ tags = (sub == nil ? [] : [sub.downcase])
+ if es[3] != nil
+ tags = tags + es[3].lstrip.split(',')
+ end
+ tags.map {|v| v.lstrip!}
+ @entries << Song.new(name, artist, genre, sub, tags + [genre.downcase])
+ end
+ def add_tags(entry, adds)
+ if adds[entry.artist] != nil
+ entry.add_tags(adds[entry.artist])
+ end
+ end
+ def initialize(data, adds)
+ @entries = []
+ data.each_line do |entry|
+ add_entry(entry)
+ end
+ @entries.each do |entry|
+ add_tags(entry, adds)
+ end
+ end
+ def get_songs
+ @entries
+ end
+
+ def find(criteria)
+ res = []
+ @entries.each do |song|
+ if song.satisfy_all(criteria)
+ res << song
+ end
+ end
+ res
+ end
+end
  • Идентираш с табове. Стандарта е 2 интервала. За това вече вземаме точки.
  • Няма нужда от скобите в es[2].split(',')[0].lstrip. Нито допринасят за четимостта, нито интерпретатора има нужда от тях.
  • Аналогично за tags = (sub == nil? [] : [sub.downcase])
  • sub.nil? е по-добре
  • Също: entry.add_tags adds[entry.artist] unless adds[entry.artist].nil?
  • tags.map { |v| v.lstrip! } е много странно. Може би си имал предвид tags.each { |v| v.lstrip! }. #map се ползва, когато искаш резултат в масив. #each се ползва за итерация.
  • Можеш да направиш data.lines
  • get_songs е лошо име за метод в Ruby. Конвенцията е songs.
  • res, es, has_them са недескриптивни имена
  • В конструктура на Song няма нужда да слагаш подчертавка пред параметрите. Всъщност, никой не пише Ruby код така.
  • isgood се пише is_good. И не е добро име.
  • За is_good и has_them можеш да ползваш Enumerable#any? и Enumerable#all?. По-четимо е.
  • tags.empty? вместо tags == []
  • Методите, които връщат булева стойност, която се използва в if трябва да завършват на въпросителна.
  • В Song можеш да ползваш attr_reader :name, :artist, :genre, :subgenre и :tags
  • Когато една песен няма тагове, tags трябва да върне празен масив, а не nil. По този начин мога да напиша song.tags.include? 'foo'. Иначе трябва да пиша song.tags && song.tags.include? 'foo'. Семантично по-смислено е. Ако го направиш, ще можеш да разкараш някои от проверките дали tags е nil.