2010-05-31 11 views
6

Ich habe Strings wie folgt aus:PyParsing: Ist dies die korrekte Verwendung von setParseAction()?

"MSE 2110, 3030, 4102" 

ich ausgeben möchte:

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

Das ist mein Weg, um darüber zu gehen, obwohl ich ziemlich es noch nicht gekommen:

Diese Ausgänge
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)], {}) 

Ist dies der richtige Weg, oder bin ich völlig ausgeschaltet?

Auch die Ausgabe von ist nicht ganz richtig - ich möchte course_data eine Liste von course Symbole, die im gleichen Format wie einander sind. Im Moment unterscheidet sich der erste Kurs von den anderen. (Es hat ein {}, während die andere nicht tun.)

+4

Sie sollten eine Antwort akzeptieren, denke ich. – Donovan

Antwort

5

Ist dies der richtige Weg, es zu tun, oder bin ich off total?

Es ist eine Möglichkeit, es zu tun, obwohl es natürlich andere (zB Verwendung als Parse-Aktionen zwei gebundene Methode sind - so die Instanz gehört die Methode zu können Zustand halten - eine für den Abt-Code und eine andere für die Kursnummer).

Der Rückgabewert des parseString Anrufs ist schwerer zu verbiegen (obwohl ich mir sicher bin, dass ausreichend dunkle Magie es tun wird und ich freue mich auf Paul McGuire zu erklären, wie ;-) Warum also nicht die Grenze überschreiten- Verfahren Route wie in ...:

from pyparsing import * 

DEPT_CODE = Regex(r'[A-Z]{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 

diese aussendet:

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

das, was Sie zu sein scheint benötigen, wenn ich Ihre Angaben richtig gelesen.

16

Diese Lösung merkt sich die Abteilung beim Parsen und gibt ein (dept, cursum) Tupel aus, wenn eine Nummer gefunden wird.

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) 

Ausgang:

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

Sicher, liebt PyParsing everbody. Für eine einfache Sachen wie diese Spaltung ist sooo viel einfacher zu grok:

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(',')) 
0
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 

Dies würde einen Generator für die Kurscodes geben. Eine Liste kann bei Bedarf mit list() erstellt werden, oder Sie können direkt darüber iterieren.

Verwandte Themen