2016-12-12 154 views
1

這一個通常扁平化所返回的列表是有點過長的講解,讓熊機智我:隨着pyparsing我來分析許多文本部分,如:在pyparsing

first multi segment part 123 45 67890 third multi segment part 

------------^----------- -----^------ ------------^----------- 
    Part A: alpha words B: num words Part C: alpha words 

我試圖用pp.OneOrMore每個零件:

a = pp.OneOrMore(pp.Word(pp.alphas)).setName("PART_A")('A') 
b = pp.OneOrMore(pp.Word(pp.nums)).setName("PART_B")('B') 
c = pp.OneOrMore(pp.Word(pp.alphas)).setName("PART_C")('C') 
expr = a + b + c 

當我運行這個在字符串"first multi segment part 123 45 67890 third multi segment part"我得到

- A: ['first', 'multi', 'segment', 'part'] 
- B: ['123', '45', '67890'] 
- C: ['third', 'multi', 'segment', 'part'] 

不過我想所有結果扁平狀:

- A: 'first multi segment part' 
- B: '123 45 67890' 
- C: 'third multi segment part' 

爲此,我可以使用setParseAction功能。 becasue我將有很多使用此功能結構的我延長了OneOrMore類喜歡這樣的:

class OneOrMoreJoined(pp.OneOrMore): 
    """OneOrMore with results joined to one string""" 
    def __init__(self, expr, stopOn=None, joinString=' '): 
     super(OneOrMoreJoined,self).__init__(expr, stopOn=stopOn) 
     self.setParseAction(joinString.join) 

有了這個類,我得到了想要的結果。 :-)

但是我能做些什麼,如果我想要一個序列d1 + d2要加入?:

d1 = pp.Word(pp.nums).setName("PART_D1") 
d2 = pp.Word(pp.alphas).setName("PART_D2") 
expr = (d1 + d2)('D') 

當然我的創建一個新類AndJoined和使用AndJoined(d1,d2),但後來我失去了漂亮的符號d1 + d2

是否有通用的方法來平坦化結果? 我當然可以手動拼合ParseResult 後,我檢索字典,但我懷疑有一個簡單的方法來表達這種pyparsing ...

+0

如果有句話之間的多個空格,你要的結果只有一個空間,或與原始字符串中的空格相同? – PaulMcG

+0

所有的空白空間都應該縮小到單個空格(就像'OneOrMoreJoined'類所要做的那樣)。 – halloleo

回答

1

最簡單的將是寫一個小幫手像這樣:

joiner = lambda expr: expr.addParseAction(' '.join) 

然後在你的語法插入joiner地方:

a_b_c = joiner(a + b + c | d + Optional(e)) 

只要確保傳遞給joiner的令牌只是單級令牌。如果它們是嵌套的,那麼你可能需要一個拼合程序,但是這是很容易通過編寫joiner作爲補充道:

joiner = lambda expr: expr.addParseAction(flatten, ' '.join) 
+0

我喜歡這種方法 - 它保持語法清潔!但是,定義的函數「flatten」在哪裏? – halloleo

+0

這是留給學生的練習。 – PaulMcG

+0

好吧,只是想檢查是否有(遞歸)'flatten'預定義的地方... – halloleo