Итеративно захватывайте подгруппы регулярных выражений в Scala

Я не знаю, как захватить подгруппы регулярных выражений в Scala.

Скажем, зелья либо простые, либо сделаны из других зелий, и они называются <adjective> <noun>. Существуют следующие формулы рецептов:

val recipe = "white phial potion is 3 fortify health potions, 1 vigorous stamina potion, 5 plentiful magicka potions."

Я хочу проанализировать формулы в следующем домене:

case class Potion(name: String)
case class Formula(potion: Potion, ingredients: Option[List[(Potion, Int)]])

Пока я придумал шаблон

val recipePattern: Regex = """(\w+ \w+) potion is( (\d+) (\w+ \w+) (?:potion|potions)[,.])+""".r

но я понятия не имею, как продолжить и захватить итерационные подгруппы.

Это невозможно сделать, потому что значение повторяющейся группы захвата перезаписывается при каждой итерации.

Wiktor Stribiżew 10.12.2020 18:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Невозможно захватить повторяющиеся группы с помощью регулярных выражений. Последнее совпадение определенной группы перезапишет все предыдущие совпадения той же группы.

Я рекомендую использовать подходящую библиотеку синтаксического анализа для анализа таких строк. Например, используя fastparse:

import scala.util.{Try, Success, Failure}

case class Potion(name: String)
object Potion {
  def apply(adjective: String, noun: String): Potion = Potion(s"$adjective $noun")
}

case class Formula(potion: Potion, ingredients: List[(Potion, Int)])
object Formula {
  import fastparse._, SingleLineWhitespace._

  object Parser {
    def number[_: P] = P(CharsWhileIn("0-9").!).map(_.toInt)
    def word[_: P] = P(CharsWhileIn("a-z").!)
    def ingredient[_: P] = P(number ~ word ~ word ~ "potion"~~"s".?).map {
      case (count, adj, noun) => (Potion(adj, noun), count)
    }
    def formula[_: P] = P(word ~ word ~ "potion" ~ "is" ~ ingredient.rep(sep = ",") ~ "." ~ End).map {
      case (adj, noun, ingredients) => Formula(Potion(adj, noun), ingredients.toList)
    }
  }

  def parse(formula: String): Try[Formula] = {
    fastparse.parse(formula, Parser.formula(_)) match {
      case Parsed.Success(result, _) => Success(result)
      case failure: Parsed.Failure => Failure(new RuntimeException(failure.trace().longMsg))
    }
  }
}

Результат:

scala> Formula.parse("white phial potion is 3 fortify health potions, 1 vigorous stamina potion, 5 plentiful magicka potions.")
res0: scala.util.Try[core.Test.Formula] = Success(Formula(Potion(white phial),List((Potion(fortify health),3), (Potion(vigorous stamina),1), (Potion(plentiful magicka),5))))

Другие вопросы по теме

Похожие вопросы

Отрицательный взгляд назад не работает должным образом. Как предотвратить захват строки второй группой?
Поиск текста с помощью регулярного выражения NEAR
Регулярное выражение для поиска текста после последнего появления символа до другого
Python Regex: добавьте ограничение, что это НЕ должно быть совпадением, если где-то перед совпадением есть кавычка И где-то после
Как я могу определить правило перезаписи, чтобы принимать также пустую строку в дополнение к a-zA-Z-?
Извлечение всех строк на основе двух столбцов с использованием Regex в postgresql
Почему производительность двух регулярных выражений, использующих группы захвата, сильно различается?
Вытащите студентов, которые получили B в файле, используя регулярное выражение
Очистка телефонных номеров с помощью регулярных выражений
Разделение строки с помощью вложенных скобок только на верхнем уровне, где «уровень» определяется скобками