2012-04-03 16 views
10

Sto cercando di analizzare le stringhe del modulo:Can not Get pyparsing Dict() per restituire dizionario nidificato

'foo(bar:baz;x:y)' 

mi piacerebbe i risultati da restituire in forma di dizionario nidificato, vale a dire per la stringa di cui sopra, i risultati dovrebbero apparire così:

{ 'foo' : { 'bar' : 'baz', 'x' : 'y' } } 

Nonostante le numerose combinazioni di Dict() e di gruppo() non riesco a farlo funzionare. La mia (una delle versioni di) grammatica si presenta così:

import pyparsing as pp 
field_name = pp.Word(pp.alphanums) 
field_value = pp.Word(pp.alphanums) 
colon = pp.Suppress(pp.Literal(':')) 

expr = pp.Dict( 
    pp.Group( 
     field_name + \ 
     pp.nestedExpr( 
      content = pp.delimitedList( 
       pp.Group(field_name + colon + field_value), 
       delim = ';' 
      ) 
     ) 
    ) 
) 

e ora, i risultati sono i seguenti:

In [62]: str = 'foo(bar:baz;x:y)' 

In [63]: expr.parseString(str).asList() 
Out[63]: [['foo', [['bar', 'baz'], ['x', 'y']]]] 

In [64]: expr.parseString(str).asDict() 
Out[64]: {'foo': ([(['bar', 'baz'], {}), (['x', 'y'], {})], {})} 

In [65]: print(expr.parseString(str).dump()) 
Out[65]: [['foo', [['bar', 'baz'], ['x', 'y']]]] 
     - foo: [['bar', 'baz'], ['x', 'y']] 

così la versione asList() sembra abbastanza buono con me e dovrebbe produrre un dizionario Sto cercando di pensare. Naturalmente dato che (nel modo in cui lo capisco, per favore correggimi) Dict() analizzerà le liste di token usando il primo elemento dell'elenco come chiave e tutti gli altri come valori di quella chiave in un dizionario. Questo funziona in quanto il dizionario non è nidificato. Per esempio in questo caso:

expr = pp.Dict( 
    pp.delimitedList( 
     pp.Group(field_name + colon + field_value), 
     delim = ';' 
    ) 
) 

In [76]: expr.parseString('foo:bar;baz:x').asDict() 
Out[76]: {'baz': 'x', 'foo': 'bar'} 

Quindi, la domanda è: che cosa c'è di sbagliato con il primo caso (e la mia comprensione del problema) o forse Dict() non possono far fronte con questo caso? Potrei usare asList() e convertirlo manualmente in un dizionario, ma preferirei fare il pyparsing :)

Qualsiasi aiuto o indicazione sarebbe molto apprezzato.

Grazie.

risposta

6

due problemi:

  • ti manca un pp.Dict intorno pp.delimitedList per rendere asDict sul lavoro risultato interno correttamente
  • Siete solo chiamando asDict sul più esterno ParsingResult esempio, lasciando l'interno ParsingResult "non interpretata"

ho provato la seguente:

from pyparsing import * 
field_name = field_val = Word(alphanums) 
colon = Suppress(Literal(':')) 

expr = Dict(Group(
    field_name + 
    nestedExpr(content = 
     Dict(delimitedList( 
      Group(field_name + colon + field_value), 
      delim = ';' 
     )) 
    ) 
)) 

poi usato in questo modo:

>>> res = expr.parseString('foo(bar:baz;x:y)') 
>>> type(res['foo']) 
<class 'pyparsing.ParseResults'> 
>>> { k:v.asDict() for k,v in res.asDict().items() } 
{'foo': {'x': 'y', 'bar': 'baz'}} 
+0

Bella presa sulla mancante 'pp.Dict'. Inoltre, prova a stampare 'res.dump()' per vedere le chiavi ei valori nidificati. (Poiché 'res' è un oggetto ParseResults, supporterà l'accesso in stile dict annidato senza conversione usando asDict:' res ['foo'] ['x'] 'restituisce 'y' oppure è possibile utilizzare la notazione degli attributi con punti come come le chiavi sono identificatori di Python: 'res.foo.bar' dà 'baz'.) – PaulMcG

+0

Ciao @Paul, bello ricevere un complimento dall'autore stesso :) Trovo' res.dump() 'non molto più informativo che semplicemente 'str (res)', ma forse non so come interpretarlo? Non avrei mai usato il pyparsing prima, dovrei dire. –

+0

Grazie mille Niklas! Non ero a conoscenza del fatto che all'interno dei risultati ci siano anche istanze di ParseResults, ho pensato che sarebbero già state liste o dizioni. Paul - grazie per il consiglio di usare come dict senza conversione, questo potrebbe davvero tornare utile in quello a cui sto lavorando! :) – kgr

Problemi correlati