6

Можно ли разделить строку на лексемы как-то, какScala: разбить строку по шаблону

"[email protected]" match { 
    case name :: "@" :: domain :: "." :: zone => doSmth(name, domain, zone) 
} 

Других слова, по тому же самому способу, как списки ...

+0

Я не уверен, если вы можете это сделать, но я могу объяснить, почему ваш пример не работает. По сути, у вас есть сопоставление для списка строк, потому что класс '' :: 'case '(https://github.com/scala/scala/blob/v2.10.3/src/library/scala/collection/immutable /List.scala#L356), также известный как «cons», строит список из элементов. Вам нужен класс case, который принимает два списка и объединяет их, подобно оператору ':::' (но, к сожалению, нет класса ':::' case, как и для cons). – joescii

ответ

19

Да, вы можете сделать это с функциональностью Scala Regex.

Я нашел email regex on this site, не стесняйтесь использовать другой, если это не устраивает:

[-0-9a-zA-Z.+_][email protected][-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4} 

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

([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4}) 

С этим мы имеем три группы: часть до @, между @ и ., и, наконец, TLD.

Теперь мы можем создать регулярное выражение Scala от него, а затем использовать в Scala pattern matching unapply, чтобы получить группы из Regex, связанные с переменными:

val Email = """([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z]{2,4})""".r 
Email: scala.util.matching.Regex = ([-0-9a-zA-Z.+_]+)@([-0-9a-zA-Z.+_]+)\.([a-zA-Z] {2,4}) 


"[email protected]" match { 
    case Email(name, domain, zone) => 
     println(name) 
     println(domain) 
     println(zone) 
} 

// user 
// domain 
// com 
+5

+1 Это легко один из самых приятных способов, с которыми я встречал регулярные выражения для дескрипторов языка. Намного лучше, чем альтернатива на многих языках, заставляя вас вручную обращаться к объекту 'groups' и находить правильное совпадение по индексу или имени. Хороший ответ. – KChaloux

3

В общем регулярное выражение ужасно неэффективно, поэтому не советовал бы.

Вы можете сделать это с помощью сопоставления шаблонов Scala, вызвав .toList на вашей строке, чтобы включить его в список [Char]. Затем ваши части name, domain и zone также будут List [Char], чтобы вернуть их обратно в Strings, используйте .mkString. Хотя я не уверен, насколько это эффективно.

Я тестировал базовые операции с строкой (например, подстрока, indexOf и т. Д.) Для различных вариантов использования vs regex, а регулярное выражение обычно на порядок или два медленнее. И, конечно, регулярное выражение ужасно нечитаемо.

UPDATE: Самое лучшее, что нужно сделать, это использовать парсер, либо родной тот Scala, или Parboiled2

+0

Whaaat? Вы постоянно перестраиваете регулярное выражение? Точка регулярных выражений состоит в том, что они создают «машины», которые могут быть сопоставлены с строками очень эффективно. Кроме того, использование регулярных выражений для очень небольших проверок не имеет смысла, но для более сложных совпадений я бы ожидал большой экономии эффективности, особенно в том случае, если число, через которое проходили входные данные, растет. –

+1

@ KenoguLabz. Конструкция регулярных выражений не находится за пределами эталона. Когда я последний раз ездил на конференцию Scala eXchange, я видел, что разговор, в котором утверждается использование парсеров (или собственный Scala 'StringOps'), обычно в 100-1000 раз быстрее. Очевидно, что если регулярное выражение построено плохо, разница в скорости может быть еще больше (поиск обратного отслеживания http://www.regular-expressions.info/catastrophic.html). Мои собственные тесты обычно выполняются на реальных данных, состоящих из миллиардов записей. – samthebest

+0

@samthebest Я очень заинтересован в этом, так как я нахожу регулярное выражение как язык, недостижимый. Как [scala Parsers] (https: // github.ком/scala/scala-parser-combinators) превосходят скомпилированные регулярные автоматы? насколько вы уверены в этом, или можете ли вы уточнить, в каких сценариях? голые кости «StringOps», конечно, слишком низкий уровень для поддержки кода с ... вряд ли хороший вариант для более чем тех случаев, когда конкретный метод подходит для вашей небольшой ad-hoc необходимости. Позаботьтесь о разработке здесь и/или в ответе? – matanster

Смежные вопросы