2012-04-03 9 views
10

Próbuję analizować ciągi w postaci:Can not Get pyparsing Dict(), aby powrócić zagnieżdżone słownika

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

Chciałbym wyniki mają być zwracane w postaci zagnieżdżonego słownika, czyli dla powyższego napisu, wyniki powinny wyglądać następująco:

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

Pomimo licznych kombinacjach Dict() i Grupy() nie mogę zmusić go do pracy. My (jedna z wersji) gramatyka wygląda następująco:

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 = ';' 
      ) 
     ) 
    ) 
) 

i teraz, wyniki są następujące:

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']] 

Więc wersja asList() wygląda całkiem dobre dla mnie i powinna przynieść słownika Poszukuję. Oczywiście biorąc pod uwagę to (sposób, w jaki to rozumiem, proszę poprawić) Dict() przeanalizuje listy tokenów, używając pierwszego elementu listy jako klucza, a resztę jako wartości tego klucza w słowniku. Działa to, o ile słownik nie jest zagnieżdżony. Na przykład w takim przypadku:

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'} 

Więc pytanie jest, co jest złego w pierwszym przypadku (i mojego zrozumienia problemu) czy może Dict() nie może poradzić sobie z takim przypadku? Mógłbym użyć asList() i przekonwertować to ręcznie do słownika, ale wolałbym, żeby to zrobiło pypars :)

Każda pomoc lub wskazówki będą mile widziane.

Dziękuję.

Odpowiedz

6

Dwa problemy:

  • tracisz pp.Dict wokół pp.delimitedList aby asDict na wewnętrznej pracy wynikowej poprawnie
  • Jesteś tylko nazywając asDict na najdalszym ParsingResult przykład, pozostawiając wewnętrzny ParsingResult „przedrostkiem nieinterpretowanym”

próbowałem następujące:

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 = ';' 
     )) 
    ) 
)) 

Następnie użył go tak:

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

Niezły chwyt na brakującej 'pp.Dict'. Spróbuj także wydrukować 'res.dump()', aby zobaczyć zagnieżdżone klucze i wartości. (Ponieważ 'res' jest obiektem ParseResults, będzie obsługiwał zagnieżdżony dostęp w stylu Dict bez konwersji za pomocą asDict:' res ['foo'] ['x'] 'daje 'y' lub możesz użyć notacji z kropkami jako o ile klucze są ładne, identyfikatory Pythona: 'res.foo.bar' daje 'baz'.) – PaulMcG

+0

Witam @Paul, miło otrzymuję komplement od samego autora :) Znajduję' res.dump() 'niewiele więcej informacji niż "str (res)", ale może po prostu nie wiem jak to interpretować? Nigdy nie używam pyparsingów, powinienem powiedzieć. –

+0

Dziękuję bardzo Niklas! Nie wiedziałem, że w wynikach są również instancje ParseResults, myślałem, że będą już listami lub dyktami. Paul - dzięki za wskazówkę, jak używać dicta bez konwersji, może się to przydać w tym, nad czym pracuję! :) – kgr

Powiązane problemy