Python 检查对象属性是否存在于对象列表中
我有一个具有不同属性的对象和一个包含这些对象的列表 在向列表中添加对象之前,我想检查列表中是否存在此新对象的属性 此属性是唯一的,因此这样做是为了确保列表中的每个对象都是唯一的 我会这样做:Python 检查对象属性是否存在于对象列表中,python,Python,我有一个具有不同属性的对象和一个包含这些对象的列表 在向列表中添加对象之前,我想检查列表中是否存在此新对象的属性 此属性是唯一的,因此这样做是为了确保列表中的每个对象都是唯一的 我会这样做: for post in stream: if post.post_id not in post_list: post_list.append(post) else: # Find old post in the list and replace it 但显然
for post in stream:
if post.post_id not in post_list:
post_list.append(post)
else:
# Find old post in the list and replace it
但显然,第2行不起作用,因为我正在将
post\u id
与对象列表进行比较 保留一个单独的集合,向其中添加属性,然后根据该集合测试下一个值:
ids_seen = set()
for post in stream:
if post.post_id not in ids_seen:
post_list.append(post)
ids_seen.add(post.post_id)
另一个选项是创建第一个,ID作为键:
posts = OrderedDict((post.post_id, post) for post in stream)
post_list = list(posts.values())
这将为给定的id
保留最近看到的post
引用,但您仍然只保留唯一的id
如果顺序不重要,只需使用常规词典:
posts = {post.post_id: post for post in stream}
post_list = list(posts.values())
如果您使用的是Python 3.6或更高版本,那么在更新CPython实现以保留输入顺序时,顺序将保持不变,并且在Python 3.7中,此功能已成为语言规范的一部分
无论您做什么,都不要使用单独的列表来测试post.id
,因为每次检查id是否存在时都需要O(N)个时间,其中N是最后流中的项目数。结合O(N)类检查,这种方法需要O(N**2)个二次时间,这意味着输入项的数量每增加10倍,处理它们的时间也会增加100倍
但是当使用集合或字典时,测试id是否已经存在只需要O(1)个常量时间,因此检查很便宜。这使得一个完整的处理循环需要O(N)个线性时间,这意味着它需要的时间与您拥有的输入项的数量成正比。这应该可以工作
for post in stream:
if post.post_id not in [post.post_id for post in post_list]:
post_list.append(post)
如果您可以控制
post
类,那么您可以创建一个\uuuuuuuuuuuuuuuuu散列
方法并在那里使用post\u id
的值,然后只需执行post\u list=set(stream)
@Peter:考虑到这不会保持顺序<代码>列表(OrderedDict.fromkeys(stream))会按照第一次看到的id的顺序保存输入。啊,是的,公平地说,从他措辞的方式来看,我认为顺序并不重要,但我并没有认真考虑:这是非常低效的,因为不在
必须对您生成的列表进行完整扫描。您还可以在每次迭代中重新生成post\u id
列表。这种组合是致命的,使得这成为一种只需要O(N**3)线性时间的O(N**3)二次方法。对于1000个项目,你的方法需要的时间大约是O(N)线性方法的100万倍。因此,如果你有耐心的话,它应该是有效的。当输入序列变长时(10k项、慢1亿倍、100k项、慢100亿倍等),这会迅速消耗时间。