在Python中,哪种数据结构的最佳方法?
我在使用Python时遇到了一些情况:
我正在解析一个本体(ontology),想要记录一些属性,并构建一个数据结构,具体要求如下:
- 每个值都有一个唯一的键来访问
- 这个值是另一个键值对的数据结构,包含以下三个部分:
'x':[] 这是一个简单的列表
'y':[{'name':value,'type':value}] 这是一个包含特定字典键值对的列表
'z':[{'name':value,'type':value}] 这也是一个包含特定字典键值对的列表
根据以上要求,我想出的最终数据结构是:
ontology={'': [{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
最后,我想要这个字典的多个条目。我不想使用列表,因为列表的索引是整数,而我希望通过键来索引我的数据。
我会在三个不同的循环中填充这个数据结构。
在第一个循环中,我会用键名填充本体字典。我想的方式是:
ontology['a']={'a': [{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
但是这样做是否符合Python的标准方式?有没有其他更方便的方法?因为我觉得这样有点奇怪。
最后,我会得到类似这样的结构:
ontology['a']={'a':[{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
ontology['b']={'b':[{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
ontology['c']={'c':[{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
ontology['d']={'d':[{'y': {'type': '','name':''}}],'x':[],'z':[ {'type': '', 'name': ''}]}
在第二个循环中,根据键来填充x:[]的值,这本身也是另一个字典。
在第三个循环中,我会填充y和z这两个键。
这样的方法适合这个数据结构吗?我也考虑过使用类(Classes),这样我的代码会更“结构化”,但我觉得这样会用更多的代码行。
3 个回答
为什么不使用XML呢?ElementTree是Python自带的一个库,它提供了一个轻量级的XML接口。使用它的好处是,你可以很方便地创建层次化的数据结构,而且所有用来遍历和查询这些结构的工具都已经准备好了。下面这个例子展示了如何创建一个简单的XML片段,
from xml.etree import ElementTree
element = ElementTree.Element
xmlprint = ElementTree.tostring
o = element('ontology')
for key in ['a','b']:
o.append(element(key,name=key))
for c in o.getchildren():
c.append(element('type'))
print xmlprint(o)
运行后会得到,
<ontology><a name="a"><type /></a><b name="b"><type /></b></ontology>
要“仅用关键名称填充本体字典”:
ontology = {}.fromkeys('abcd',{})
或者
ontology = dict( (k,{}) for k in 'abcd')
然后你会把ontology中每个项目的{}填充为'a':[...]、'b':[...]、'c':[...]这些内容。
但是我不明白为什么要把值ontology['a']['a']写成一个只包含一个字典的列表,而这个字典里只有一个项目,并且这个项目的键'y'总是相同。
比如说,写这个值'a':[{'y': {'type': 'DSE','name':'JHG'}}],你可以直接写成'a':('DSE','JHG')。知道第一个元素是类型,第二个是名称。
你也可以写'z':('QSZA','IUYOIU'),同样知道第一个是类型,第二个是名称。
所以本体字典会是:
{'a': {'a':('DSE','JHG') , 'x':[...] , 'z':('QSZA','IUYOIU')} ,
'b': {'b':('dfg','tfy') , 'x':[...] , 'z':('ynyu','zertzt')} ,
'c': {'c':('noq','jek') , 'x':[...] , 'z':('frEZ','jkyukA')} ,
'd': {'d':('bqi','bif') , 'x':[...] , 'z':('kiy',';jheTri')} }
而且它甚至可以进一步简化:
{'a': (('a', 'DSE','JHG') , [...] , ('QSZA','IUYOIU')) ,
'b': (('b', 'dfg','tfy') , [...] , ('ynyu','zertzt')) ,
'c': (('c', 'noq','jek') , [...] , ('frEZ','jkyukA')) ,
'd': (('d', 'bqi','bif') , [...] , ('kiy',';jheTri')) }
本体字典中值的第一个元素总是以('a', 类型, 名称)的形式出现,第二个总是以'x'的形式出现的列表,第三个总是以'z'的形式出现的(类型, 名称)对。
这些元素('a', 类型, 名称)、[...]、(类型, 名称)可以通过位置0、1、2来访问,而不是通过键'a'+'y'、'x'、'z'。
"代码行数"可能不是最好的优化标准。这看起来像是一个经典的例子,说明你可能已经超出了用“字典和列表”来解决问题的能力。我之前也遇到过很多次这种情况。建议你使用类,这样可以让你的代码更易懂、更好维护,并且可以为操作你的数据结构写上有意义的方法。
这样做会给你带来灵活性,可以在不改变数据的含义或调用者对数据的看法的情况下,隐藏和更改底层的存储方式。