Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby regex matching strings from an array?

Tags:

ruby

I'm sort of new to regexs with Ruby, (or I suppose regex in general), but I was wondering if there was a pragmatic way to match a string using an array?

Let me explain, say I have a list of ingredients in this case:

1 1/3 cups all-purpose flour
2 teaspoons ground cinnamon
8 ounces shredded mozzarella cheese

Ultimately I need to split the ingredients into its respective "quantity and measurement" and "ingredient name", so like in the case of 2 teaspoons ground cinnamon, will be split into "8 ounces, and shredded mozzarella cheese.

So Instead of having a hugely long regex like: (cup\w*|teaspoon\w*ounce\w* ....... ), how can I use an array to hold those values outside the regex?


update

I did this (thanks cwninja):

  # I think the all units should be just singular, then 
  # use ruby function to pluralize them.

units = [
  'tablespoon',
  'teaspoon',
  'cup',
  'can',
  'quart',
  'gallon',
  'pinch',
  'pound',
  'pint',
  'fluid ounce',
  'ounce'
  # ... shortened for brevity
]

joined_units = (units.collect{|u| u.pluralize} + units).join('|')

# There are actually many ingredients, so this is actually an iterator
# but for example sake we are going to just show one.
ingredient = "1 (10 ounce) can diced tomatoes and green chilies, undrained"

ingredient.split(/([\d\/\.\s]+(\([^)]+\))?)\s(#{joined_units})?\s?(.*)/i)

This gives me close to what I want, so I think this is the direction I want to go.

puts "measurement: #{arr[1]}"
puts "unit: #{arr[-2] if arr.size > 3}"
puts "title: #{arr[-1].strip}"
like image 649
JP Silvashy Avatar asked Oct 18 '10 21:10

JP Silvashy


People also ask

How do you match a string in Ruby?

Ruby | Regexp match() functionRegexp#match() : force_encoding?() is a Regexp class method which matches the regular expression with the string and specifies the position in the string to begin the search. Return: regular expression with the string after matching it.

What does =~ mean in Ruby regex?

=~ is Ruby's basic pattern-matching operator. When one operand is a regular expression and the other is a string then the regular expression is used as a pattern to match against the string. (This operator is equivalently defined by Regexp and String so the order of String and Regexp do not matter.

Can you use regex in Ruby?

Ruby regex: Putting It All TogetherRegular expressions can be used with many Ruby methods.


2 Answers

Personally I'd just build the regexp programmatically, you can do:

ingredients = [...]
recipe = Regexp(ingredients.join("|"), true) # Case-insensitive

or using union method:

recipe = Regexp.union(ingredients)
recipe = /#{regex}/i

… then use the recipe regexp.

As long as you save it and don't keep recreating it, it should be fairly efficient.

like image 187
cwninja Avatar answered Sep 23 '22 10:09

cwninja


For an array a, something like this should work:

a.each do |line|
    parts = /^([\d\s\.\/]+)\s+(\w+)\s+(.*)$/.match(line)
    # Do something with parts[1 .. 3]
end

For example:

a = [
    '1 1/3 cups all-purpose flour',
    '2 teaspoons ground cinnamon',
    '8 ounces shredded mozzarella cheese',
    '1.5 liters brandy',
]
puts "amount\tunits\tingredient"
a.each do |line|
    parts = /^([\d\s\.\/]+)\s+(\w+)\s+(.*)$/.match(line)
    puts parts[1 .. 3].join("\t")
end
like image 26
mu is too short Avatar answered Sep 20 '22 10:09

mu is too short