如何解决将唯一项添加到列表我需要关注性能吗? 输出:
我想检查每次迭代中是否有新项目出现在列表B
中,如果是,则将新值附加到A
中。从我的研究中,我得出的结论是,这是解决此问题的最常用方法(不使用集合,我想使列表保持有序):
A = ['aa','bb','cc']
B = ['aa','cc','dd','ee'] # Read only
[A.append(b) for b in B if not b in A]
但是,这种方法在计算上似乎很繁琐,我想知道这种关注是否合理?如果是这样,还有另一种性能更好的方法吗?
我知道B
不会经常更新(可能少于迭代的1%),并且A
可能拥有{{1}中不存在的更多值},但应保留。
解决方法
您只能通过拦截append / insert / extend调用来对添加到B的新项(而不是全部)执行此操作。然后,仅将逻辑应用于传入的元素。
因为B不会得到频繁的更新,但显然可能会变得很大,因此应该或多或少地满足您的要求。如果您真的想花哨的话,甚至可以管理一个set
来保存已经存在的值,但这是以速度为代价的内存交换,我将等着看实际的分析,以了解复杂性是否值得。
A = ['aa','bb','cc']
B = ['aa','cc','dd','ee'] # Read only
[A.append(b) for b in B if not b in A]
class myB:
def __init__(self,A,B):
self.li = B
self.A = A
def insert(self,i,x):
self.li.insert(i,x)
if not x in self.A:
self.A.append(x)
def append(self,x):
self.li.append(x)
if not x in self.A:
self.A.append(x)
#override extend...
#set up intercept
B2 = myB(A,B)
print(f"ante:{A=}")
print(f"ante:{B=}")
B2.append("xx")
B2.append("ee")
print(f"\npost:{A=}")
您还可以使用class myB(list):
,即子类化而不是修饰。
输出:
ante:A=['aa','ee']
ante:B=['aa','ee']
post:A=['aa','ee','xx']
p.s。不必太挑剔,但是Python命名约定强烈建议不要使用大写的变量名,例如A,Bcd,这些通常表示您正在处理类变量。
,请勿使用list
,其中set
更合适(就O(n)
而言,速度要快得多)。作为一个简单的例子,
a_list,b_list = ['aa','bb'],['aa','cc']
a_set = set(a_list)
for b in b_list:
if b in a_set:
continue
a_set.add(b)
a_list.append(b)
查看文档以了解更多详细信息。
P.S。这是一个经典的权衡:为了性能而牺牲RAM。
,使用虚拟值更新字典可能更快,并且(键的)列表保持有序。但是,这在Python> = 3.6中有效。对于以前的版本,您可以使用from collections import OrderedDict
。
unique_elems = {'aa': None,'bb': None,'ee': None}
unique_elems.update({'aa': None,'cc': None,})
list(unique_elems.keys())
['aa','cc']