用于解析(格式不良)属性列表的算法

时间:2012-04-23 19:31:13

标签: python

我知道我已经看到了一个很好的算法,但找不到它。

我从一个需要解析的工具(我无法控制的输出样式)输出(格式不佳)。

它看起来像这样:

NameOfItemA
attribute1 = values1
attribute2 = values2
...
attributen = valuesn
NameOfItemB
attribute1 = values1
attribute2 = values2
...
attributen = valuesn        

其中NameOfItemX和attributeX是一组明确定义的已知名称。需要把它变成合理的对象:

ObjectForA.attribute1 = values1

我知道我以前做过这件事,只是不记得我是怎么做到的。它看起来像是:

for line in textinput:
    if line.find("NameOfItem"):
        ... parse until next one ...

希望我说的是有道理的,有人可以提供帮助

4 个答案:

答案 0 :(得分:2)

这与mgilson的答案类似,不过它将数据放在嵌套字典中。

from collections import defaultdict
itemname = None
d = defaultdict(dict)
for line in data:
    line = line.rstrip()
    if '=' in line:
        attr, value = line.split('=',1)
        d[itemname][attr] = value
    else:
        itemname = line

答案 1 :(得分:1)

将它作为嵌套字典怎么样:

x = {'NameOfItemA': {'attribute1': 'value1', 'attribute2': 'value2'},...}

然后您可以将值引用为:

value2 = x['NameOfItemA']['attribute2']

并且,假设该属性,值始终遵循标题,例如NameOfItemN

items = {}
for line in textinput:
    if line.find("NameOfItem"):
        headline = line
        inner_dict = {}
        items[headline] = inner_dict
    else:
        attr, val = line.split('=',1)
        items[headline][attr] = val

答案 2 :(得分:1)

这是一个你可能感兴趣的pyparsing解决方案。我已经添加了很多评论来完成代码。

data = """\
NameOfItemA
attribute1 = values1A
attribute2 = values2A
attributen = valuesnA
NameOfItemB
attribute1 = values1B
attribute2 = values2B
attributen = valuesnB
"""

from pyparsing import Suppress, Word, alphas, alphanums, \
              empty, restOfLine, Dict, OneOrMore, Group

# define some basic elements - suppress the '=' sign because, while
# it is important during the parsing process, it is not an interesting part
# of the results
EQ = Suppress('=')
ident = Word(alphas, alphanums)

# an attribute definition is an identifier, and equals, and whatever is left
# on the line; the empty advances over whitespace so lstrip()'ing the
# values is not necessary
attrDef = ident + EQ + empty + restOfLine

# define a section as a lone ident, followed by one or more attribute 
# definitions (using Dict will allow us to access attributes by name after 
# parsing)
section = ident + Dict(OneOrMore(Group(attrDef)))

# overall grammar is defined as a series of sections - again using Dict to
# give us attribute-name access to each section's attributes
sections = Dict(OneOrMore(Group(section)))

# parse the string, which gives back a pyparsing ParseResults
s = sections.parseString(data)

# get data using dotted attribute notation
print s.NameOfItemA.attribute2

# or access data like it was a nested dict
print s.keys()
for k in s.keys():
    print s[k].items()

打印:

values2A
['NameOfItemB', 'NameOfItemA']
[('attribute2', 'values2B'), ('attribute1', 'values1B'), ('attributen', 'valuesnB')]
[('attribute2', 'values2A'), ('attribute1', 'values1A'), ('attributen', 'valuesnA')]

答案 3 :(得分:0)

怎么样:

class obj(object): pass
items={}
for line in textinput:
    if(line.find("NameOfItem")!=-1):
       current_object=items[line.replace("NameOfItem","")]=obj()
    else:
       attr,val=line.split('=',1)
       setattr(current_object,attr.strip(),val.strip())

当然,如果你已经有一个想要使用的类,你可以省略基本对象... 毕竟说完了,你有一个对象字典,其中有keys = object_names和values = attributes(作为字符串 - 你需要转换成它应该是什么类型,如果它不是一个字符串)

另请注意,此输入文件格式与ConfigParser模块的 A LOT 类似。您可以读取该文件并将"NameOfItem"行更改为[item]行,并将其作为StringIO对象传递给ConfigParser ...