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