PyParsing: Правильно ли это использование setParseAction ()?

У меня есть строки вроде этого:

"MSE 2110, 3030, 4102" 

Я хотел бы вывести:

 [("MSE", 2110), ("MSE", 3030), ("MSE", 4102)] 

Это мой способ обойти это, хотя я еще не получил его еще:

 def makeCourseList(str, location, tokens): print "before: %s" % tokens for index, course_number in enumerate(tokens[1:]): tokens[index + 1] = (tokens[0][0], course_number) print "after: %s" % tokens course = Group(DEPT_CODE + COURSE_NUMBER) # .setResultsName("Course") course_data = (course + ZeroOrMore(Suppress(',') + COURSE_NUMBER)).setParseAction(makeCourseList) 

Эти результаты:

 >>> course.parseString("CS 2110") ([(['CS', 2110], {})], {}) >>> course_data.parseString("CS 2110, 4301, 2123, 1110") before: [['CS', 2110], 4301, 2123, 1110] after: [['CS', 2110], ('CS', 4301), ('CS', 2123), ('CS', 1110)] ([(['CS', 2110], {}), ('CS', 4301), ('CS', 2123), ('CS', 1110)], {}) 

Это правильный способ сделать это, или я полностью отключен?

Кроме того, вывод не совсем корректен – я хочу, чтобы в course_data был course_data список символов course которые находятся в том же формате, что и другие. Прямо сейчас, первый курс отличается от других. (У этого есть {} , тогда как другие нет.)

4 Solutions collect form web for “PyParsing: Правильно ли это использование setParseAction ()?”

Это решение запоминает отдел при анализе и испускает кортеж (dept, coursenum) при обнаружении числа.

 from pyparsing import Suppress,Word,ZeroOrMore,alphas,nums,delimitedList data = '''\ MSE 2110, 3030, 4102 CSE 1000, 2000, 3000 ''' def memorize(t): memorize.dept = t[0] def token(t): return (memorize.dept,int(t[0])) course = Suppress(Word(alphas).setParseAction(memorize)) number = Word(nums).setParseAction(token) line = course + delimitedList(number) lines = ZeroOrMore(line) print lines.parseString(data) 

Вывод:

 [('MSE', 2110), ('MSE', 3030), ('MSE', 4102), ('CSE', 1000), ('CSE', 2000), ('CSE', 3000)] 

Это правильный способ сделать это, или я полностью отключен?

Это один из способов сделать это, хотя, конечно, есть и другие (например, использовать в качестве действий синтаксического анализа два связанных метода), поэтому экземпляр, к которому принадлежит метод, может содержать состояние – один для кода депт, а другой для номера курса).

Возвращаемое значение вызова parseString сложнее сгибать по вашему желанию (хотя я уверен, что достаточно темная магия сделает это, и я с нетерпением жду, когда Пол МакГуайр объяснит, как ;-), так почему бы не пойти по методу связанного метода, как в …:

 from pyparsing import * DEPT_CODE = Regex(r'[AZ]{2,}').setResultsName("DeptCode") COURSE_NUMBER = Regex(r'[0-9]{4}').setResultsName("CourseNumber") class MyParse(object): def __init__(self): self.result = None def makeCourseList(self, str, location, tokens): print "before: %s" % tokens dept = tokens[0][0] newtokens = [(dept, tokens[0][1])] newtokens.extend((dept, tok) for tok in tokens[1:]) print "after: %s" % newtokens self.result = newtokens course = Group(DEPT_CODE + COURSE_NUMBER).setResultsName("Course") inst = MyParse() course_data = (course + ZeroOrMore(Suppress(',') + COURSE_NUMBER) ).setParseAction(inst.makeCourseList) ignore = course_data.parseString("CS 2110, 4301, 2123, 1110") print inst.result 

это испускает:

 before: [['CS', '2110'], '4301', '2123', '1110'] after: [('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')] [('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')] 

который, кажется, вам нужен, если я правильно прочитаю ваши спецификации.

Конечно, все любят PyParsing. Для простых вещей, таких как этот раскол, намного проще пробить:

 data = '''\ MSE 2110, 3030, 4102 CSE 1000, 2000, 3000''' all = [] for row in data.split('\n'): klass,num_l = row.split(' ',1) all.extend((klass,int(num)) for num in num_l.split(',')) 
 data = '''\ MSE 2110, 3030, 4102 CSE 1000, 2000, 3000''' def get_courses(data): for row in data.splitlines(): department, *numbers = row.replace(",", "").split() for number in numbers: yield department, number 

Это даст генератор кодов курсов. Список может быть сделан со list() если это необходимо, или вы можете перебирать его напрямую.

Python - лучший язык программирования в мире.