在Python中,哪种数据结构的最佳方法?

2 投票
3 回答
1321 浏览
提问于 2025-04-16 12:17

我在使用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 个回答

0

为什么不使用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>
1

要“仅用关键名称填充本体字典”:

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

8

"代码行数"可能不是最好的优化标准。这看起来像是一个经典的例子,说明你可能已经超出了用“字典和列表”来解决问题的能力。我之前也遇到过很多次这种情况。建议你使用类,这样可以让你的代码更易懂、更好维护,并且可以为操作你的数据结构写上有意义的方法。

这样做会给你带来灵活性,可以在不改变数据的含义或调用者对数据的看法的情况下,隐藏和更改底层的存储方式。

撰写回答