Robert Klemme
2/13/2005 5:52:00 PM
"Francis Hwang" <sera@fhwang.net> 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