7

我希望能够从一段文本中提取字母的类型和数量,其中字母可以按任何顺序排列。我还在进行其他一些解析,但这一点让我很困惑!

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()
4

5 回答 5

6

一种解决方案:

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

不涉及 pyparsing,但这似乎有点矫枉过正。

于 2010-01-25T18:38:58.470 回答
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) 处理 1 到 n 的重复。解析操作负责将解析的标记转换为 (character, count) 元组。

于 2010-01-26T03:15:28.400 回答
3

我喜欢Lennart 的单线解决方案

如果您使用的是 3.1,Alex 提到了另一个不错的选择

另一个选项是collections.defaultdict

>>> from collections import defaultdict
>>> mydict = defaultdict(int)
>>> for c in 'bbbc':
...   mydict[c] += 1
...
>>> mydict
defaultdict(<type 'int'>, {'c': 1, 'b': 3})
于 2010-01-25T19:00:55.317 回答
2

如果你想要一个纯 pyparsing 的方法,这感觉是对的:

from pyparsing import *

# lambda to define expressions
def makeExpr(ch):
    expr = Literal(ch).setResultsName(ch, listAllMatches=True)
    return expr

expr = OneOrMore(MatchFirst(makeExpr(c) for c in "abc"))
expr.setParseAction(lambda tokens: [[a,len(b)] for a,b in tokens.items()])


tests = """\
abc
bbbc
cccaa
""".splitlines()

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

印刷:

abc [['a', 1], ['c', 1], ['b', 1]]
bbbc [['c', 1], ['b', 3]]
cccaa [['a', 2], ['c', 3]]

但这开始进入一个晦涩的代码领域,因为它依赖于 pyparsing 的一些更神秘的特性。一般来说,我喜欢使用 defaultdict 的频率计数器(还没有尝试过 Counter),因为很清楚你在做什么。

于 2010-01-26T03:08:28.730 回答
1

pyparsing 分开——在 Python 3.1 中,collections.Counter使此类计数任务变得非常容易。Counter可以在此处找到适用于 Python 2的好版本。

于 2010-01-25T18:51:15.997 回答