Петко обнови решението на 31.10.2011 15:12 (преди около 13 години)
+class Song
+ attr_accessor :name, :artist, :genre, :subgenre, :tags
+ def initialize(metadata = {})
+ metadata.each { |key, value| instance_variable_set("@#{key}", value) }
+ end
+ def matches(criteria = {})
+ criteria.each do |key, value|
+ case key
+ when :tags
+ return false unless matches_taglist(value)
+ when :filter
+ return false unless value.(self)
+ else
+ return false unless instance_variable_get("@#{key}").include? value
+ end
+ end
+ return true
+ end
+ def matches_taglist(*taglist)
+ taglist.flatten.each do |tag|
+ if tag.end_with? "!"
+ return false if @tags.include? tag.chop
+ else
+ return false unless @tags.include? tag
+ end
+ end
+ return true
+ end
+end
+
+#/^(?<name>.*?)\.\s+(?<artist>[^\s].*?)(\.\s+((?<genre>.*?)(,\s+(?<subgenre>.*?)
+#)?)(\.\s+(?<tags>.*?))?)?$/
+#Освен че е красиво, работи даже и проверява дали имаме задължителните полета...
+#Жалко, че се оказа ненужно и чупеше максималната позволена дължина на ред... :(
+class Collection
+ def initialize(input = "", additional_tags = {})
+ @collection = []
+ input.each_line { |song| add song.strip }
+
+ additional_tags.each do |artist, taglist|
+ find(artist: artist).each { |song| song.tags=song.tags | taglist }
+ end
+ end
+ def add(song)
+ meta = song.split(/\. */)
+ meta[2] = meta[2].split(/, */)
+ meta[3] = tag_array(meta[1..3])
+ @collection << Song.new(name: meta[0], artist: meta[1], genre: meta[2][0],
+ subgenre: meta[2][1], tags: meta[3])
+ end
+ def find(condition = {})
+ [] + @collection.select {|song| song.matches condition}
+ end
+ def tag_array(*arguments)
+ result = []
+ arguments.flatten.each do |taglist|
+ result |= taglist.downcase.split(/, */) unless taglist == nil
+ end
+ result
+ end
+end