我有这样的字符串:
"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
符号列表,这些符号的格式彼此相同。现在,第一门课程与其他课程不同。 (它有一个{}
,而其他的没有。)
答案 0 :(得分:16)
此解决方案在解析时记住部门,并在找到数字时发出(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)]
答案 1 :(得分:5)
这是正确的方式吗,或者是 我完全离开了?
这是实现它的一种方法,当然还有其他方法(例如用作解析动作的两个绑定方法 - 因此方法所属的实例可以保持状态 - 一个用于部门代码而另一个用于课程编号)。
parseString
召唤的回归值更难以屈服于你的意愿(虽然我确定黑暗魔法会做到这一点,我期待Paul McGuire解释如何;-),为什么不去绑定方法路由,如...:
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
这会发出:
before: [['CS', '2110'], '4301', '2123', '1110']
after: [('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')]
[('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')]
如果我正确阅读您的规格,似乎就是您所需要的。
答案 2 :(得分:0)
当然,每个人都喜欢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(','))
答案 3 :(得分: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
这将为课程代码提供生成器。如果需要,可以使用list()
创建列表,或者您可以直接迭代它。