Георги обнови решението на 28.10.2011 12:42 (преди около 14 години)
+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.
Коментарите са още актуални.
Табовете ти струват една точка.
