Различать совпадения в pyparsing

Я хочу разбирать некоторые слова и некоторые цифры с пирарированием. Простое право.

from pyparsing import * A = Word(nums).setResultsName('A') B = Word(alphas).setResultsName('B') expr = OneOrMore(A | B) result = expr.parseString("123 abc 456 7 d") print result 

Вышеприведенный код печатает ['123', 'abc', '456', '7', 'd'] . Так что все сработало. Теперь я хочу выполнить некоторую работу с этими анализируемыми значениями. Для этой задачи мне нужно знать, соответствуют ли они A или B Есть ли способ различать эти два.

Единственное, что я нашел после некоторых исследований, – это метод ParseResults класса ParseResults . Но он возвращает только [('A', '7'), ('B', 'd')] , только последние два совпадения.

Мой план / цель заключается в следующем:

 for elem in result: if elem.is_of_type('A'): # do stuff elif elem.is_of_type('B'): # do something else 

Как я различаю A и B ?

3 Solutions collect form web for “Различать совпадения в pyparsing”

Хорошая работа с getName (). Вы также можете явно украсить возвращенные маркеры маркером, указав, какой матч был сделан:

 def makeDecoratingParseAction(marker): def parse_action_impl(s,l,t): return (marker, t[0]) return parse_action_impl A = Word(nums).setParseAction(makeDecoratingParseAction("A")) B = Word(alphas).setParseAction(makeDecoratingParseAction("B")) expr = OneOrMore(A | B) result = expr.parseString("123 abc 456 7 d") print result.asList() 

дает:

 [('A', '123'), ('B', 'abc'), ('A', '456'), ('A', '7'), ('B', 'd')] 

Теперь вы можете перебирать возвращаемые кортежи, и каждый из них помечен соответствующим маркером.

Вы можете сделать это еще дальше и использовать класс для захвата как типа, так и специфичной для типа логики пост-анализа, а затем передать класс как действие разбора выражения. Это создаст экземпляры классов в возвращаемых ParseResults, которые затем можно выполнить непосредственно с помощью какого-либо метода exec или doIt :

 class ResultsHandler(object): """Define base class to initialize location and tokens. Call subclass-specific post_init() if one is defined.""" def __init__(self, s,locn,tokens): self.locn = locn self.tokens = tokens if hasattr(self, "post_init"): self.post_init() class AHandler(ResultsHandler): """Handler for A expressions, which contain a numeric string.""" def post_init(self): self.int_value = int(self.tokens[0]) self.odd_even = ("EVEN","ODD")[self.int_value % 2] def doIt(self): print "An A-Type was found at %d with value %d, which is an %s number" % ( self.locn, self.int_value, self.odd_even) class BHandler(ResultsHandler): """Handler for B expressions, which contain an alphabetic string.""" def post_init(self): self.string = self.tokens[0] self.vowels_count = sum(self.string.lower().count(c) for c in "aeiou") def doIt(self): print "A B-Type was found at %d with value %s, and contains %d vowels" % ( self.locn, self.string, self.vowels_count) # pass expression-specific handler classes as parse actions A = Word(nums).setParseAction(AHandler) B = Word(alphas).setParseAction(BHandler) expr = OneOrMore(A | B) # parse string and run handlers result = expr.parseString("123 abc 456 7 d") for handler in result: handler.doIt() 

Печать:

 An A-Type was found at 0 with value 123, which is an ODD number A B-Type was found at 4 with value abc, and contains 1 vowels An A-Type was found at 8 with value 456, which is an EVEN number An A-Type was found at 12 with value 7, which is an ODD number A B-Type was found at 14 with value d, and contains 0 vowels 

Я не совсем понимаю, почему, но в ваших .setResultsName() вам нужно указать listAllMatches=True (по умолчанию это False ). Как только вы это сделаете, вы можете просмотреть result и проверить, соответствует ли каждый токен данным выражением, проверяя принадлежность к соответствующему предмету result .

 from pyparsing import * # ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ A = Word(nums ).setResultsName('A', listAllMatches=True) B = Word(alphas).setResultsName('B', listAllMatches=True) expr = OneOrMore(A | B) result = expr.parseString("123 abc 456 7 d") for elem in result: if elem in list(result['A']): print(elem, 'is in A') elif elem in list(result['B']): print(elem, 'is in B') 

Это печатает:

 123 is in A abc is in B 456 is in A 7 is in A d is in B 

Это kludgey, и я не уверен, что это канонически-правильный способ сделать это, но, похоже, это работает.

Я нашел решение самостоятельно. Класс ParseResults имеет метод getName() . Но просто повторяя result и печатая getName() выдает ошибки, так как объект ParseResults дает строки. Одним из решений является включение A и B в Groups . Не уверен, что это лучший способ, но он работает очень хорошо.

 from pyparsing import * A = Group(Word(nums)).setResultsName('A', listAllMatches=True) B = Group(Word(alphas)).setResultsName('B', listAllMatches=True) expr = OneOrMore(A | B) result = expr.parseString("123 abc 456 7 d") for i in result: if i.getName() == 'A': print i[0], 'is a number' elif i.getName() == 'B': print i[0], 'is a string' 
  • Названия PyQt4, отображаемые как неопределенные в eclipse, но они отлично работают
  • Использовать печать внутри лямбда
  • VirtualEnv / Pip пытается установить пакеты по всему миру
  • Python 2.7: мгновенно пишите в файл
  • Ошибка Python - Quickfix: getHeader () при попытке войти в систему
  • Простое имя пользователя и пароль в Python
  • Как получить IDLE, чтобы принять вставку символов Юникода?
  • Заполнение непрерывного кадра данных pandas из разреженного кадра данных
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.