2016-11-18 6 views
2

У меня есть простой пример, где я бы хотел разобрать 2 строки данных.Как получить список значений из объекта результата в PyParsing?

In [1] from pyparsing import Word, nums, OneOrMore, Optional, Suppress, alphanums, LineEnd, LineStart 

     Float = Word(nums + '.' + '-') 
     Name = Word(alphanums) 
     Line = OneOrMore(Float)('data') + Suppress(Optional(';')) + Optional('%') + Optional(Name)('name') 

     Lines = OneOrMore(Line + LineEnd()) 

     string = ''' 1 10 0  T20 
      1 76 0 T76 
     ''' 
     result = Lines.parseString(string) 

In [2] result 
Out[2] (['1', '10', '0', 'T20', '\n', '1', '76', '0', 'T76', '\n'], {'data': [(['1', '10', '0'], {}), (['1', '76', '0'], {})], 'name': ['T20', 'T76']}) 

В результате объект содержит все значения I требуют, то есть значения data и name ключей списки с пунктами упорядоченного на основе линии. Как получить значения из объекта результата?

Доступ к атрибут данных не дает обоих рядов

In [3] result.data 
Out[3] (['1', '76', '0'], {}) 

In [4] for i in result.data: 
      print i 
     1 
     76 
     0 

Метод asDict() возвращает только второй строке

In [5]: result.asDict() 
Out[5]: {'data': ['1', '76', '0'], 'name': 'T76'} 

Метод asList() возвращает всю информацию в одном списке, и трудно перечислить, если вы не знаете длину name и data досрочно

In [6]: result.asList() 
Out[6]: ['1', '10', '0', 'T20', '\n', '1', '76', '0', 'T76', '\n'] 

asXML() содержит все, что мне нужно, но оно находится в формате XML, а в докстерии говорится, что он будет устаревшим в ближайшее время.

In [7]: print result.asXML() # The documentation says this will be deprecated 
     <data> 
      <data>1</data> 
      <ITEM>10</ITEM> 
      <ITEM>0</ITEM> 
      <name>T20</name> 
      <ITEM> 
     </ITEM> 
      <data>1</data> 
      <ITEM>76</ITEM> 
      <ITEM>0</ITEM> 
      <name>T76</name> 
      <ITEM> 
     </ITEM> 
     </data> 

dump() снова частично содержит соответствующую информацию, но она возвращает строку, и нужно было бы разобрать строку еще раз для получения информации.

In [8]: print result.dump() 
     ['1', '10', '0', 'T20', '\n', '1', '76', '0', 'T76', '\n'] 
     - data: ['1', '76', '0'] 
     - name: 'T76' 

Как получить эти значения в виде Pythonic?

ответ

1

Хорошо, используя имена результатов, они невероятно полезны при доступе к разборным полям. Но это звучит, как вам нужно добавить слой структурирования для вашего синтаксического анализа, так что каждая строка получает собственные данные, имя и т.д. Вы можете сделать это просто переосмысление линии, как:

Lines = OneOrMore(Group(Line) + LineEnd().suppress()) 

Теперь, если вы печать (result.dump()) вы получите:

[['1', '10', '0', 'T20'], ['1', '76', '0', 'T76']] 
[0]: 
    ['1', '10', '0', 'T20'] 
    - data: ['1', '10', '0'] 
    - name: 'T20' 
[1]: 
    ['1', '76', '0', 'T76'] 
    - data: ['1', '76', '0'] 
    - name: 'T76' 

выход сброса() не предназначен для разбора, чтобы получить значение, оно призвано помочь показать вам, как структурированные значения могут быть получены. Например, вы можете сделать:

print(result[1].data) 
print(result[1].name) 

и получить

['1', '76', '0'] 
T76 

или:

for parsed_line in result: 
    print("{name}: {data}".format_map(parsed_line)) 

и получите:

T20: ['1', '10', '0'] 
T76: ['1', '76', '0'] 
+1

Вау спасибо за подробный и очень полезный ответ Павел. Мне очень нравится, как вы не только даете отличный ответ на заданный вопрос, но и всегда можете прокрасться в некоторые дополнительные лакомые кусочки там (я до сих пор не знал о format_map) :) Еще раз спасибо, и отличная работа на пакете ! – kdheepak