2010-10-18 19 views
5

Sono una specie di nuovo regex con Ruby, (o suppongo regex in generale), ma mi chiedevo se c'era un modo pragmatico per abbinare una stringa utilizzando un array?Ruby regex le stringhe corrispondenti da un array?

Mi spiego meglio, dire che ho un elenco degli ingredienti, in questo caso:

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

In definitiva ho bisogno di dividere gli ingredienti nella rispettiva "quantità e valutazione" e "ingrediente", così come in il caso di 2 teaspoons ground cinnamon, sarà suddiviso in "8 ounces e shredded mozzarella cheese

Così, invece di avere un enorme lunga regex come:. (cup\w*|teaspoon\w*ounce\w* .......), come posso usare un allineamento per contenere questi valori al di fuori della regex

?

aggiornamento

ho fatto questo (grazie 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) 

Questo mi dà vicino a quello che voglio, quindi penso che questa è la direzione che voglio andare.

puts "measurement: #{arr[1]}" 
puts "unit: #{arr[-2] if arr.size > 3}" 
puts "title: #{arr[-1].strip}" 

risposta

22

Personalmente avevo appena costruire il regexp programatically, si può fare :

misure = [...] MEASUREMENTS_RE = Regexp.new (measurements.join ("|"))

... quindi utilizzare regexp.

Finché lo si salva e non si continua a ricrearlo, dovrebbe essere abbastanza efficiente.

+7

anche io uso questo approccio, con un piccolo ritocco: Regexp.union (misure) invece di Regexp.new (measurement.join ("|")), stesso risultato, molto più pulito – Coelhone

3

Per una matrice un, qualcosa come questo dovrebbe funzionare:

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

Ad esempio:

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 
+0

+ 1 Grazie per la tua risposta, stranamente la tua risposta è giusta per il modo sciocco che ho descritto il mio problema, non penso di essere stato molto chiaro, ma la tua soluzione è in realtà molto buona per il modo in cui l'ho descritta . –

Problemi correlati