From: Robert Klemme Date: 2005-02-14T02:54:57+09:00 Subject: Re: "Joining" strings which may be nil (or) Handling Option hashes "Francis Hwang" schrieb im Newsbeitrag news:0682b7cb1757683cfdf7811804277529@fhwang.net... > On Feb 13, 2005, at 11:44 AM, Robert Klemme wrote: >> Lots of, here are some: >> >>>> opts = {"title"=>"ruby", "author"=>"dave", "publisher"=>"oreilly", >>>> "foo"=>nil} >> => {"title"=>"ruby", "author"=>"dave", "foo"=>nil, >> "publisher"=>"oreilly"} >>>> opts.select{|k,v|v} >> => [["title", "ruby"], ["author", "dave"], ["publisher", "oreilly"]] >>>> opts.select{|k,v|v}.map{|k,v| "#{k}=#{v}"}.join(" and ") >> => "title=ruby and author=dave and publisher=oreilly" >> >> Here's a more efficient variant - using #inject of course :-) >> >>>> opts.inject(nil){|s,(k,v)| v ? (s ? s << " and " : "") << k << "=" << v >>>> : s} >> => "title=ruby and author=dave and publisher=oreilly" > > Maybe the OP isn't worried about this, but: Is there a way to represent > ORs as well as ANDs if you're doing this? You could provide multiple values for a key and create an OR from that: opts = {"title"=>["ruby","foobar"], "author"=>"dave"} opts.inject(nil) do |s,(k,v)| if v (s ? s << " and " : "") << (Enumerable === v && ! (String === v) ? v.inject(nil) {|s2,v2| (s2 ? s2 << " or " : "(") << k << ":" << v2} << ")" : "#{k}:#{v}") else s end end Slightly unreadable... :-)) You don't need the outer if-else-end though if v is never nil. Kind regards robert