python - 嵌套字典/列表混合的Python自定义类在尝试删除空的时会自行清空
问题描述
我创建了一个自定义类来帮助跟踪 QTreeWidget 内的 QTreeWidgetItems,树有三个级别,并且项目被标识为这样 [a]、[a、b]、[a、b、c] 和 a、b , c 是 类型的变量int
,[a, b, c] 标识位于 的项目tree.topLevelItem(a).child(b).child(c)
。
班级做什么?它将一个字符串列表作为输入,并输出一个整数列表,该列表由各个级别的元素的索引组成。
例如,假设类的一个对象包含以下“键”:
['a', 'a', 'a'],
['a', 'a', 'b'],
['a', 'a', 'c'],
['a', 'b', 'a']
如果给出以下输入,它将输出指定的输出:
['a', 'a', 'a'] -> [0,0,0]
['a', 'a', 'b'] -> [0,0,1]
['a', 'a', 'c'] -> [0,0,2]
['a', 'b', 'a'] -> [0,1,0]
['a', 'a'] -> [0,0]
['a', 'b'] -> [0,1]
['a'] -> [0]
该类有两个列表,一个名为 的列表Keys
,它包含字符串,另一个名为的列表Values
,该Values
列表包含同一类的其他对象。
Keys
列表和列表始终具有相同的Values
长度和一一对应关系,这意味着对于Keys
位于 index的任何键i
,其对应项位于Values[i]
。
该类在概念上类似于嵌套dict
s,尤其是defaultdict
,并且我使用嵌套的两层defaultdict
来创建树,但是 Python 字典没有索引,这就是该类的重点。
班上:
import json
from itertools import product
class TreeList:
def __init__(self):
self.Keys = list()
self.Values = list()
def add(self, k):
if k[0] not in self.Keys:
self.Keys.append(k[0])
self.Values.append(TreeList())
i = self.Keys.index(k[0])
if len(k) > 1:
child = self.Values[i]
k.pop(0)
child.add(k)
def getValue(self, k, indexes=list()):
if k[0] in self.Keys:
i = self.Keys.index(k[0])
indexes = indexes.copy()
indexes.append(i)
if len(k) == 1:
return indexes
child = self.Values[i]
k.pop(0)
return child.getValue(k, indexes)
def delete(self, k):
if k[0] in self.Keys:
i = self.Keys.index(k[0])
if len(k) == 1:
self.Keys.remove(k[0])
self.Values.pop(i)
else:
child = self.Values[i]
k.pop(0)
child.delete(k)
self.recurRemoveEmpty()
def removeEmpty(self):
for v in self.Values.copy():
if not v.Keys:
i = self.Values.index(v)
self.Values.remove(v)
self.Keys.pop(i)
def recurRemoveEmpty(self):
for v in self.Values.copy():
v.removeEmpty()
self.removeEmpty()
def to_dict(self):
return {k: self.Values[i].toDict() for i, k in enumerate(self.Keys)}
def pretty(self):
return json.dumps(self.toDict(), indent=4)
def clear(self):
self.__init__()
一些例子:
tree = TreeList()
for i in product('abc', repeat=3): tree.add(list(i))
for i in product('abc', repeat=3): print(tree.getValue(list(i)))
输出:
[0, 0, 0]
[0, 0, 1]
[0, 0, 2]
[0, 1, 0]
[0, 1, 1]
[0, 1, 2]
[0, 2, 0]
[0, 2, 1]
[0, 2, 2]
[1, 0, 0]
[1, 0, 1]
[1, 0, 2]
[1, 1, 0]
[1, 1, 1]
[1, 1, 2]
[1, 2, 0]
[1, 2, 1]
[1, 2, 2]
[2, 0, 0]
[2, 0, 1]
[2, 0, 2]
[2, 1, 0]
[2, 1, 1]
[2, 1, 2]
[2, 2, 0]
[2, 2, 1]
[2, 2, 2]
问题是,如果我删除任何值,对象会意外地清空自己。
例如:
In [417]: tree.getValue(['a', 'a', 'a'])
Out[417]: [0, 0, 0]
In [418]: tree.getValue(['a', 'a', 'b'])
Out[418]: [0, 0, 1]
In [419]: tree.delete(['a', 'a', 'a'])
In [420]: tree.getValue(['a', 'a', 'b'])
In [421]:
它是由recurRemoveEmpty
功能引起的,少不了removeEmpty
。
如果我删除这两个功能,一切正常:
In [424]: tree.getValue(['a', 'a', 'b'])
Out[424]: [0, 0, 1]
In [425]: tree.delete(['a', 'a', 'a'])
In [426]: tree.getValue(['a', 'a', 'b'])
Out[426]: [0, 0, 0]
In [427]: tree.getValue(['a', 'a', 'c'])
Out[427]: [0, 0, 1]
In [428]: tree.delete(['a', 'a', 'b'])
In [429]: tree.getValue(['a', 'a', 'c'])
Out[429]: [0, 0, 0]
In [430]:
问题是,如果没有子项,我的树会删除二级项,如果没有子项,则删除顶级项,在我的自定义类中,只有三级项会自动递减,这意味着如果从第二级项目中删除所有第三级项目,则在树中该项目将被删除,但在自定义类中该项目不会被自动删除,从而导致索引不一致,如果再次使用删除功能。
所以这removeEmpty
是必要的,但它不会产生预期的结果。
预期的结果是,在上面的例子中,tree.getValue(['a', 'b', 'a'])
应该[0,0,0]
在 之后返回['a', 'a', 'a']
,['a', 'a', 'b']
并被['a', 'a', 'c']
删除。
这个怎么做?
我通过将删除自定义类中的项目的代码显式添加到删除树中的空项目的代码来规避了这一点。
不过,我仍然想知道如何在内部自动完成这样的事情。
解决方案
推荐阅读
- powershell - Add-Content -PassThru is writing to file but not passing output to console
- amazon-web-services - 无法登录。Tableau SAML 中的用户名或密码无效
- bootstrap-4 - 如何为移动设备将 flex cloumns 包装在单行中
- actionscript-3 - Actionscript 表演滑稽
- c# - 根据方法参数值获取枚举值
- google-apps-script - g-suite Google Calender Apps 事件保存/更新脚本
- python - 使用显示坐标从轴到绝对图形坐标的转换在 matplotlib 中不起作用
- typescript - 推断传递的属性名称的值
- wordpress - Woocommerce 修改或重置 total_sales
- dialogflow-es - 当他们说话时,如何确保在 Dialogflow 中收到正确的用户电子邮件?