2010-10-18 8 views
5

Jestem w pewnym sensie nowy dla wyrażeń regularnych z Ruby (lub ogólnie rzecz biorąc regex), ale zastanawiałem się, czy istnieje pragmatyczny sposób na dopasowanie ciągu znaków za pomocą tablicy?Ruby dopasowujące ciągi regex z tablicy?

Pozwól mi wyjaśnić, że mam listę składników w tym przypadku:

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

Ostatecznie muszę podzielić składniki w odpowiedniej „ilości i miary” oraz „Nazwa składnika”, tak jak w przypadek 2 teaspoons ground cinnamon, zostanie podzielona na "8 ounces i shredded mozzarella cheese

więc zamiast o niezwykle długiej regex takich jak:. (cup\w*|teaspoon\w*ounce\w* .......), w jaki sposób można wykorzystać tablicę do przechowywania tych wartości poza regex

?

aktualizacja

zrobiłem to (dzięki 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) 

To daje mi blisko tego, co chcę, więc myślę, że jest to kierunek chcę iść.

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

Odpowiedz

22

osobiście bym tylko budować regexp programowo, można zrobić :

pomiary = [...] MEASUREMENTS_RE = Regexp.new (measurement.join ("|"))

... następnie użyj wyrażenia regularnego.

Dopóki go zapisujesz i nie odtwarzasz go ponownie, powinna być dość wydajna.

+7

Używam również tego podejścia, z małą korektą: Regexp.union (pomiary) zamiast Regexp.new (measurement.join ("|")), ten sam wynik, znacznie czystszy – Coelhone

3

Na tablicy , coś jak to powinno działać:

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

Na przykład:

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 Dziękuję za twoją odpowiedź, co dziwne, twoja odpowiedź brzmi jak od razu w głupi sposób, w jaki opisałam mój problem, nie sądzę, że byłam bardzo jasna, ale twoje rozwiązanie jest naprawdę dobre dla sposobu, w jaki to opisałem . –