2016-12-12 6 views
1

Dieses pyparsing ist ein bisschen lengthly, zu erklären, so tragen wit me:Allgemeinen zurück Listen in Flatten

first multi segment part 123 45 67890 third multi segment part 

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

Ich versuchte pp.OneOrMore für jeden Teil zu nutzen: Mit pyparsing ich viele Textteile wie analysieren müssen:

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 

Als ich dies über die Schnur laufen "first multi segment part 123 45 67890 third multi segment part" ich

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

Allerdings möchte ich alle Ergebnisse abgeflacht wie:

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

Dazu kann ich die setParseAction-Funktion verwenden. becasue ich eine Menge von Konstrukten mit dieser Funktion haben wird verlängert ich die OneOrMore Klasse gefällt:

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) 

Mit dieser Klasse I das gewünschte Ergebnis zu erhalten.

:-)

aber was kann ich tun, wenn ich eine Sequenz d1 + d2 zu verbinden ?: wollen

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

Natürlich habe ich eine neue Klasse erstellen AndJoined und verwenden AndJoined(d1,d2), aber dann verliere ich die nette Notation d1 + d2.

Gibt es eine allgemeine Möglichkeit, Ergebnisse zu glätten? Ich könnte natürlich glätte die parseResult manuell außerhalb, nachdem ich die dict abrufen, aber ich vermute, es ist eine einfache Möglichkeit, diese innerhalbpyparsing auszudrücken ...

+0

Wenn es mehrere Leerzeichen zwischen den Wörtern sind, haben Sie das Ergebnis wollen nur einen Raum zu haben, oder die gleiche Leerzeichen wie in der ursprünglichen Zeichenfolge? – PaulMcG

+0

Der gesamte Leerraum sollte auf einzelne Leerzeichen verkleinert werden (wie es die 'OneOrMoreJoined' Klasse tun sollte). – halloleo

Antwort

1

Die einfachste einen kleinen Helfer zu schreiben wäre wie folgt aus:

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

Dann joiner in Ihrer Grammatik einfügen, wo immer:

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

Stellen Sie nur sicher, dass die Token, die an joiner übergeben werden, nur einzelne Level-Tokens sind. Wenn sie verschachtelt sind, dann könnten Sie eine flattener Routine brauchen, aber dies wird leicht hinzugefügt von joiner wie das Schreiben:

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

Ich mag diesen Ansatz - es hält die Grammatik sauber! Aber wo ist die Funktion 'flatten' definiert? – halloleo

+0

Dies ist eine Übung für den Schüler. – PaulMcG

+0

Ok, wollte nur prüfen, ob es eine ist (rekursiv) 'flatten' irgendwo vordefiniert ... – halloleo