我有两个列表,让我们说:
a = [1,2,3]
b = [1,2,3,1,2,3]
我想从列表b中删除1,2和3,但不是全部删除。结果列表应该有:
b = [1,2,3]
我目前有:
for element in a:
try:
b.remove(element)
except ValueError:
pass
然而,当a和b变得非常大时,这种性能很差。是否有更有效的方法来获得相同的结果?
修改
澄清'并非所有事件',我的意思是我不希望从b中删除'1',因为a中只有一个'1'。
答案 0 :(得分:2)
我会这样做:
set_a = set(a)
new_b = []
for x in b:
if x in set_a:
set_a.remove(x)
else:
new_b.append(x)
与其他设定解决方案不同,这会维持b
中的顺序(如果您关心这一点)。
答案 1 :(得分:1)
我会做这样的事情:
from collections import defaultdict
a = [1, 2, 3]
b = [1, 2, 3, 1, 2, 3]
# Build up the count of occurrences in b
d = defaultdict(int)
for bb in b:
d[bb] += 1
# Remove one for each occurrence in a
for aa in a:
d[aa] -= 1
# Create a list for all elements that still have a count of one or more
result = []
for k, v in d.iteritems():
if v > 0:
result += [k] * v
或者,如果你愿意稍微晦涩难懂:
from operator import iadd
result = reduce(iadd, [[k] * v for k, v in d.iteritems() if v > 0], [])
defaultdict生成每个键的出现次数。从b
构建后,a
中每次出现一个键时,它都会递减。然后我们打印出仍然遗留下来的元素,允许它们多次出现。
defaultdict适用于python 2.6及更高版本。如果您使用的是更高版本的python(我认为是2.7及更高版本),您可以查看collections.Counter
。
后来:您也可以对此进行概括并创建计数器式默认值的减法:
from collections import defaultdict
from operator import iadd
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
def build_dd(lst):
d = defaultdict(int)
for item in lst:
d[item] += 1
return d
def subtract_dd(left, right):
return {k: left[k] - v for k, v in right.iteritems()}
db = build_dd(b)
da = build_dd(a)
result = reduce(iadd,
[[k] * v for k, v in subtract_dd(db, da).iteritems() if v > 0],
[])
print result
但reduce
表达式现在非常模糊。
稍后:在python 2.7及更高版本中,使用collections.Counter
,它看起来像这样:
from collections import Counter
base = [1, 2, 3]
missing = [4, 5, 6]
extra = [7, 8, 9]
a = base + missing
b = base * 4 + extra
result = Counter(b) - Counter(a)
print result
assert result == dict([(k, 3) for k in base] + [(k, 1) for k in extra])
答案 2 :(得分:1)
一般来说,你总是要避免使用list.remove()(你是对的,它会严重损害性能)。此外,在字典或集合中查找元素比在列表中查找要快得多(O(1));所以从list1创建一个集合(如果顺序无关紧要,则从列表2中创建)。
这样的事情:
sa = set(a)
new_b = [x for x in b if not x in sa]
# here you created a 3d list but I bet it's OK.
但是我不知道你选择拆除元素的实际算法是什么。请详细说明“但不是所有事件”。