From: Dark Ambient Date: 2006-08-14T06:12:11+09:00 Subject: Re: Search objects That's a lot of food :) Stuart On 8/13/06, ara.t.howard@noaa.gov wrote: > 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 > >