Ruby регулярные выражения сопоставления строк из массива? - PullRequest
6 голосов
/ 19 октября 2010

Я в некотором роде новичок в регулярных выражениях с Ruby (или, скорее всего, в регулярных выражениях), но мне было интересно, существует ли прагматический способ сопоставления строки с использованием массива?

Позвольте мне объяснить, скажем, у меня есть список ингредиентов в этом случае:

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

В конечном итоге мне нужно разделить ингредиенты на соответствующие «количество и измерение» и «название ингредиента», так что, как и в случае 2 teaspoons ground cinnamon, они будут разбиты на «8 ounces и shredded mozzarella cheese.

Итак, вместо огромного длинного регулярного выражения, например: (cup\w*|teaspoon\w*ounce\w* ....... ), как я могу использовать массив для хранения этих значений вне регулярного выражения?


обновление

Я сделал это (спасибо 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)

Это приближает меня к тому, чего я хочу, поэтому я думаю, что это направление, в котором я хочу идти.

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

Ответы [ 2 ]

26 голосов
/ 19 октября 2010

Лично я бы просто построил регулярное выражение программно, вы можете сделать:

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

или использовать union метод:

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

… затем использовать recipe регулярное выражение.

Пока вы сохраняете его и не продолжаете его воссоздавать, он должен быть достаточно эффективным.

3 голосов
/ 19 октября 2010

Для массива a что-то вроде этого должно работать:

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

Например:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...