From: Robert Klemme Date: 2011-12-14T17:27:17+09:00 Subject: Re: How to pass a list of conditions as parameters On Wed, Dec 14, 2011 at 3:05 AM, Sam Duncan wrote: > On 14/12/11 14:28, Thescholar Thescholar wrote: >> >> I’m unsure how to explain this one so I'll do my best. >> >> Technically, I would like to pass an array of numbers and an array of >> conditions as parameters in a method. The tricky part is that I would >> like to evaluate each number of that array to each condition of that >> other array. >> >> The reason I would like to achieve something like this is because I plan >> to change the list of rules/conditions each time I want to call this >> method. But what is the desired output? That's crucial for the solution (see below). >> Here’s the unworking code so far: >> >> (see attachment) >> >> Thank you in advance for your valuable support! Any help or hyperlinks >> with explanations is greatly appreciated! >> >> Attachments: >> http://www.ruby-forum.com/attachment/6838/array_of_conditions.txt >> > Nothing pretty or fancy here, but seems to do it? Note, I think the hash > interpolation is a 1.9.x thing. > > > array_of_numbers = [0, 2, 4, 7, 10, 25] > > # these could easily come from a config file/ db/ whatevs > array_of_eval_conditions = [ "(%{number} == 2)", "(%{number} == 5 and > %{number} == 5)", "(%{number} != 1)"] > > # these could too, but would require a few more hoops > array_of_lambda_conditions = [lambda {|x| x == 2}, lambda {|x| x == 5 and x > == 5}, lambda {|x| x != 1}] Why "more hoops"? There is no point in having conditions in Strings if they are constant in the script. There is no need for eval here. Please note that an more recent versions of Ruby (at least 1.9.3) lamba implements operator === which is reasonable because then you can use a lambda as condition in a case expression and with Enumerable#grep: irb(main):004:0> pos = lambda {|x| x >= 0} => # irb(main):005:0> vals = [-10,-5,0,5,10] => [-10, -5, 0, 5, 10] irb(main):007:0> vals.each {|v| p v, pos[v], pos === v; case v;when pos;puts "pos";else puts "not" end} -10 false false not -5 false false not 0 true true pos 5 true true pos 10 true true pos => [-10, -5, 0, 5, 10] There do exists ways to do this already, e.g. assuming that conditions are in an array of lambdas: # get all which satisfy all conditions items.select {|x| conditions.all? {|c| c[v]}} # get first which satisfies all conditions items.find {|x| conditions.all? {|c| c[v]}} # get all which satisfy any condition items.select {|x| conditions.any? {|c| c[v]}} # get first which satisfies any condition items.find {|x| conditions.any? {|c| c[v]}} See also Enumerable#reject etc. Kind regards rober -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/