删除列表项(如果不在其他列表中)-python
这是我的情况。 我有一个Person对象的列表删除列表项(如果不在其他列表中)-python,python,Python,这是我的情况。 我有一个Person对象的列表 class Person(): def __init__(self, name="", age=): self.name = name self.uid = str( uuid.uuid4( ) ) self.age = age 我的UI包含一个显示这些项目的树状视图。在某些情况下,如果用户愿意,他们可以拥有同一个人的实例。我突出显示那些粗体,让用户知道是同一个人 问题 当用户删除树节点时
class Person():
def __init__(self, name="", age=):
self.name = name
self.uid = str( uuid.uuid4( ) )
self.age = age
我的UI包含一个显示这些项目的树状视图。在某些情况下,如果用户愿意,他们可以拥有同一个人的实例。我突出显示那些粗体,让用户知道是同一个人
问题
当用户删除树节点时,我需要知道是否应该从列表中删除实际对象。但是,如果正在使用该对象的另一个实例,那么我不应该删除它
我对解决方案的想法。
在执行删除操作(只删除treenode项)之前,我将收集ui中使用的所有人员
接下来,我将继续删除treeview项
接下来,获取在ui中使用的另一个objevst集合
Laslty比较两个列表并删除第二个列表中未出现的人员
如果我使用这个解决方案,我最好做一个测试,比如
for p in reversed(original_list):
if p not in new_list:
original_list.remove(p)
或者我应该收集uid编号来进行比较,而不是整个对象
名单可能相当大
Herr是我第一次尝试处理删除操作的代码。当你关闭应用程序时,它会保存一个json文件
这是我做删除的函数
def delete_treewidet_items(self, ctrl):
global NODES
root = self.treeWidget.invisibleRootItem()
# delete treewidget items from gui
for item in self.treeWidget.selectedItems():
(item.parent() or root).removeChild(item)
# collect all uids used in GUI
uids_used = self.get_used_uids( root=self.treeWidget.invisibleRootItem() )
for n in reversed(NODES):
if n.uid not in uids_used:
NODES.remove(n)
不必太担心运行时或列表的大小,您可以使用集合操作:
for p in set(original_list) - set(new_list):
original_list.remove(p)
或筛选列表:
new_original_list = [p for p in original_list if p in new_list]
但是,再说一遍,为什么要查看整个列表?当一个项目(甚至是树中的非叶节点)被删除时,您知道删除了哪个项目,因此您可以将搜索限制在该项目上。您可以使用以下方法比较对象:
>>> p1 = Person('John')
>>> p2 = Person('Billy')
>>> id(p1) == id(p2)
False
>>> p1 is p2
False
要比较对象相等性,请使用=运算符=运算符使用eq方法测试等式。若类并没有定义这样的方法,那个么它将返回到比较对象的标识
因此:
或者我应该收集uid编号来进行比较
而不是整个对象
你也会做同样的事情,因为你在课堂上没有定义情商
若要筛选列表,请在迭代列表时不要修改列表,这是错误的。猜猜将打印什么:
>>> a = [1, 2, 3]
>>> b = [1, 2]
>>> for item in a:
... if item in b:
... a.remove(item)
>>> a
[2, 3]
如果要安全地执行此操作,请从后面遍历列表,如:
>>> a = [1, 2, 3]
>>> b = [1, 2]
>>> for i in xrange(len(a) - 1, -1, -1):
... if a[i] in b:
... a.pop(i)
2
1
>>> a
[3]
您没有发布足够的代码,但我可以收集到:
import collections
import uuid
class Person():
def __init__(self, name="", age=69):
self.name = name
self.uid = str( uuid.uuid4( ) )
self.age = age
def __eq__(self, other):
return isinstance(other, Person) and self.uid == other.uid
def __ne__(self, other): return self != other # you need this
def __hash__(self):
return hash(self.uid)
# UI --------------------------------------------------------------------------
persons_count = collections.defaultdict(int) # belongs to your UI class
your_list_of_persons = [] # should be a set
def add_to_ui(person):
persons_count[person] += 1
# add it to the UI
def remove_from_ui(person):
persons_count[person] -= 1
if not persons_count[person]: your_list_of_persons.remove(person)
# remove from UI
所以基本上:
在执行删除操作(只删除treenode项)之前,我将收集ui中使用的所有人员
否-此信息始终作为用户界面中的模块变量可用-上面的人数。这样,您就不必到处复制列表
保留创建人员的代码-然后更新您的列表(其中包含不同的人员,因此应该是一个集合)。如果这是在添加到\u ui
中完成的(有意义),则应修改为:
def add_to_ui(name, age):
p = Person(name, age)
set_of_persons.add(p) # if already there won't be re-added and it's O(1)
persons_count[person] += 1
# add it to the UI
为了更进一步,您不需要原始列表,即persons\u count.keys()
,只需修改:
def add_to_ui(name, age):
p = Person(name, age)
persons_count[person] += 1
# add it to the UI
def remove_from_ui(person):
persons_count[person] -= 1
if not persons_count[person]: del persons_count[person]
# remove from UI
你明白了吗
编辑:这里是从我的最新迭代中删除的内容:
def delete_tree_nodes_clicked(self):
root = self.treeWidget.invisibleRootItem()
# delete treewidget items from gui
for item in self.treeWidget.selectedItems():
(item.parent() or root).removeChild(item)
self.highlighted.discard(item)
persons_count[item.person] -= 1
if not persons_count[item.person]: del persons_count[item.person]
我已将我的解决方案(对链接到第一个问题的代码的重写)发布在:。这是一个很好的重构练习——看看提交消息。我在这里特别介绍这条格言:
可能需要更多的工作,但我认为这是朝着正确方向迈出的一步-在大多数操作中也应该更快,并节省内存,但如果一个子节点有一堆子节点,则仅限于删除的项会导致问题。仅仅删除已删除的节点并不表示其子节点也已删除。意味着我的列表仍将包含未使用的节点。您添加到UI的代码是什么?你的代码是什么创建了一个人并使用了同一个实例?我明白了-所以真正的问题是你有“项目”,你不能从他们那里得到人-UI列表控件的常见问题。您的控制是否允许您以某种方式将项目连接到人员?Aka您可以从项目
到人员
获取信息吗?编辑:当然可以-你有一个CustomTreeNode,它基本上包装了一个perdon(为什么要调用个人数据)?根据我的答案重构你的代码,然后发回——基本上你可以删掉几行……在我在这里发帖之前,我将代码发布到了我的第一次尝试中。过来看。希望能有帮助。@JokerMartini:你应该把相关部分带到你的问题中去——没有人会免费为你阅读和调试300行代码;)更新问题,以显示有关删除的位的焦点。我在def-tk-explain中添加了注释。当我今天来到电脑前,我会试试你的解决方案。如果我的代码片段需要进一步解释,请告诉我。@JokerMartini:我在这里建立了一个回购协议来破解它:。我仍然需要一些激励,因为这是一个重写,我会给你的答案打上正确的标记,因为这是我一直在寻找的最符合逻辑的方法。我没有钱付钱给你重写它。我将更新和清理我的代码,并将其发布在github上,并在此处的原始帖子中链接到它,以便其他人可以看到它。