2010-01-25 36 views
7

我希望能夠從一段文本中提取字母的類型和數量,其中的字母可以按任意順序排列。還有一些其他解析正在進行中,但這一點讓我難住了!Pyparsing - 不可預知的令牌順序

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

回答

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

的每個構建需要匹配出故障的照顧,和Word(CH)處理1到n重複。分析動作負責將解析的標記轉換爲(字符,計數)元組。

+0

是的,字符被分組,所以這是完美的。感謝您的解答和解釋。喜歡pyparsing! – PhoebeB 2010-01-26 12:05:13

6

一個解決方案:

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

沒有pyparsing參與,但似乎有點小題大做。

+0

我想我會通過使用pyparsing來拉取塊和setParseAction來處理它。仍然有興趣知道是否有一個pyparsing解決方案! – PhoebeB 2010-01-25 20:25:08

+0

感謝您的解決方案 - 它現在已經被pyparsing分析了,但感謝您的幫助和非常完美的解決方案! – PhoebeB 2010-01-26 12:06:35

1

pyparsing apart - 在Python 3.1中,collections.Counter使得這樣的計數任務非常簡單。 Python 2的Counter的好版本可以在here找到。

+0

就像櫃檯類 - 會記住其他的事情。謝謝。 – PhoebeB 2010-01-25 20:26:56

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),因爲它很清楚你正在做什麼。