开发者

Ruby: map tags into a boolean condition to get a true/false result

开发者 https://www.devze.com 2022-12-25 22:45 出处:网络
I have an array of tags per item like so: item1 = [\'new\', \'expensive\'] item2 = [\'expensive\', \'lame\']

I have an array of tags per item like so:

item1 = ['new', 'expensive']
item2 = ['expensive', 'lame']

I also have a boolean expression as a string based on possible tags:

buy_it = "(new || expensive) && !lame"

How can I determine if an 开发者_开发技巧item matches the buying criteria based on the tags associated with it? My original thought was to do a gsub on all words in buy_it to become 'true' or 'false' based on them existing in the itemx tags array and then exec the resulting string to get a boolean result.

But since the Ruby community is usually more creative than me, is there a better solution?

EDIT:

Just to clarify, buy_it in my example is dynamic, users can change the criteria for buying something at run-time.


Along the lines of your gsub idea, instead of substituting each word for true/false every time, why not substitute each "query" into an expression that can be re-used, e.g. the example buy_it:

buy_it = "(new || expensive) && !lame"
buy_it_expr = buy_it.gsub(/(\w+)/, 'tags.include?("\1")')

puts buy_it_expr
=> (tags.include?("new") || tags.include?("expensive")) && !tags.include?("lame")

It could be evaluated into a Proc and used like this:

buy_it_proc = eval "Proc.new { |tags| #{buy_it_expr} }"

buy_it_proc.call(item1)
=> true
buy_it_proc.call(item2)
=> false

Of course, care must be taken that the expression does not contain malicious code. (One solution might be to strip all but the allowed operator characters from the string and of course be wary of exceptions during eval.)


A hash is a good candidate here.

items = {'ipad' => ['new', 'expensive'], 'kindle' => ['expensive', 'lame']}
items.each do |name,tags|
  if tags.include?('new' || 'expensive') && !tags.include?('lame')
    puts "buy #{name}."
  else
    puts "#{name} isn't worth it."
  end
end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号