Pyparsing - 当令牌顺序不可预测时

7 投票
5 回答
1237 浏览
提问于 2025-04-15 18:27

我想从一段文本中提取出字母的类型和数量,而这些字母的顺序可能是随意的。虽然我已经有其他的解析部分在正常工作,但这一部分让我感到困惑!

input -> result
"abc" -> [['a',1], ['b',1],['c',1]]
"bbbc" -> [['b',3],['c',1]]
"cccaa" -> [['a',2],['c',3]]

我可以使用搜索或扫描的方法,对每一个可能的字母进行重复操作,但有没有更简单的方法呢?

这是我目前的进展:

from pyparsing import *


def handleStuff(string, location, tokens):

        return [tokens[0][0], len(tokens[0])]


stype = Word("abc").setParseAction(handleStuff)
section =  ZeroOrMore(stype("stype"))


print section.parseString("abc").dump()
print section.parseString("aabcc").dump()
print section.parseString("bbaaa").dump()

5 个回答

3

我喜欢Lennart的那种一行代码解决方案

Alex提到的另一个不错的选择,适合你使用3.1版本。

还有一个选择是collections.defaultdict

>>> from collections import defaultdict
>>> mydict = defaultdict(int)
>>> for c in 'bbbc':
...   mydict[c] += 1
...
>>> mydict
defaultdict(<type 'int'>, {'c': 1, 'b': 3})
6

一种解决方案:

text = 'sufja srfjhvlasfjkhv lasjfvhslfjkv hlskjfvh slfkjvhslk'
print([(x,text.count(x)) for x in set(text)])

这里没有使用pyparsing这个库,不过看起来这个方法有点复杂。

6

我不太清楚你描述的输入字符是否可以像“ababc”这样混合,因为在你所有的测试案例中,字母总是被分组在一起。如果字母确实总是分组在一起,你可以使用下面的pyparsing代码:

def makeExpr(ch):
    expr = Word(ch).setParseAction(lambda tokens: [ch,len(tokens[0])])
    return expr

expr = Each([Optional(makeExpr(ch)) for ch in "abc"])

for t in tests:
    print t,expr.parseString(t).asList()

这个Each构造可以处理字符顺序不一致的情况,而Word(ch)则负责处理字符的重复次数。解析动作会把解析出来的内容转换成(字符, 计数)这样的元组。

撰写回答