PyParsing:这是正确使用setParseAction()吗?

Nic*_*ner 7 python parsing nlp pyparsing

我有这样的字符串:

"MSE 2110, 3030, 4102"
Run Code Online (Sandbox Code Playgroud)

我想输出:

[("MSE", 2110), ("MSE", 3030), ("MSE", 4102)]
Run Code Online (Sandbox Code Playgroud)

这是我的方式,虽然我还没有完成它:

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)
Run Code Online (Sandbox Code Playgroud)

这输出:

>>> 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)], {})
Run Code Online (Sandbox Code Playgroud)

这是正确的做法,还是我完全离开了?

此外,输出不太正确 - 我想course_data发出一个course彼此格式相同的符号列表.现在,第一门课程与其他课程不同.(它有一个{},而其他的没有.)

Mar*_*nen 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)
Run Code Online (Sandbox Code Playgroud)

输出:

[('MSE', 2110), ('MSE', 3030), ('MSE', 4102), ('CSE', 1000), ('CSE', 2000), ('CSE', 3000)]
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 5

这是正确的做法,还是我完全离开了?

这是实现它的一种方法,当然还有其他方法(例如,使用两个绑定方法作为解析操作 - 因此方法所属的实例可以保持状态 - 一个用于dept代码,另一个用于课程编号).

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
Run Code Online (Sandbox Code Playgroud)

这会发出:

before: [['CS', '2110'], '4301', '2123', '1110']
after: [('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')]
[('CS', '2110'), ('CS', '4301'), ('CS', '2123'), ('CS', '1110')]
Run Code Online (Sandbox Code Playgroud)

如果我正确阅读你的规格,这似乎是你需要的.