From: ara.t.howard@... Date: 2006-08-14T04:25:33+09:00 Subject: Re: Search objects On Mon, 14 Aug 2006, Dark Ambient wrote: > I can use some help here: > > I've set up this class and objects and would like to "search" it > similar to the way I would search a database. At this point I'm not > concerned with adding regex for more liberal searches. > Any suggestions ? > > class Composer > def initialize( lname, country ) > @lname = lname > @country = country > end > attr_accessor(:lname, :country) > end > > comp1 = Composer.new("Beethoven", "Germany") > comp2 = Composer.new("DeFalla", "Spain") > comp3 = Composer.new("Debussy", "France") > harp:~ > cat a.rb require 'weakref' class Composer (ATTRIBUTES = %w( lname country )).each{|a| attr_accessor a} INDEX = Hash.new{|h,k| h[k] = []} def self.find arg pattern = case arg when Hash ATTRIBUTES.map{|a| arg[a] || arg[a.to_s] || arg[a.to_s.intern]} when Array arg else raise ArgumentError end n = pattern.size keys = INDEX.keys.select do |key| match = [] n.times do |i| pat, k = pattern[i], key[i] match << if pat.nil? true elsif pat.respond_to? 'call' pat.call(k) ? true : false elsif pat.respond_to? '===' pat === k elsif pat.respond_to? '==' pat == k else false end end match.all? end INDEX.values_at(*keys).map{|list| list.map{|weakref| weakref.__getobj__}}.flatten end def initialize *argv ATTRIBUTES.each{|a| send "#{ a }=", argv.shift} key = ATTRIBUTES.map{|a| send a} val = WeakRef.new self INDEX[key] << val end def to_hash ATTRIBUTES.inject({}){|h,k| h.update k => send(k)} end def inspect to_hash.inspect end def to_s inspect end end comp1 = Composer.new "Beethoven", "Germany" comp2 = Composer.new "DeFalla", "Spain" comp3 = Composer.new "Debussy", "France" found = Composer.find 'lname' => 'Beethoven' p found found = Composer.find 'lname' => %r/^bee|^defal/io p found found = Composer.find :country => lambda{|c| c.upcase === 'SPAIN'} p found class CaseOf < ::Array def ===(other) flatten.compact.map{|pat| pat === other}.any? end end def caseof(*a, &b) CaseOf.new(*a, &b) end found = Composer.find :lname => %r/y$/, :country => caseof(%w[ Spain France ]) p found harp:~ > ruby a.rb [{"country"=>"Germany", "lname"=>"Beethoven"}] [{"country"=>"Germany", "lname"=>"Beethoven"}, {"country"=>"Spain", "lname"=>"DeFalla"}] [{"country"=>"Spain", "lname"=>"DeFalla"}] [{"country"=>"France", "lname"=>"Debussy"}] food for thought. -a -- to foster inner awareness, introspection, and reasoning is more efficient than meditation and prayer. - h.h. the 14th dali lama