我正在尝试合并两个列表base
和override
,其中base
应该是一个更大的列表,override
是其中的一部分base
。在元素重叠的地方,我希望base
中的对象被override
中的对象覆盖。每个列表中的对象都是名为的元组,其中包含属性al2000
和de2000
。此外,我希望当对象具有相同的al2000
和de2000
值时,将它们视为“相同”。我所拥有的(似乎有效)在下面,但这有嵌套循环,我想知道是否有更好的方法来做到这一点。
# Part of a function
final = []
for i in base:
if all((i.al2000, i.de2000) != (k.al2000, k.de2000) for k in override):
final.append(i)
else:
for k in override:
if (i.al2000, i.de2000) == (k.al2000, k.de2000):
final.append(k)
return final
答案 0 :(得分:1)
您可以使用for/else
构造。
final = []
for i in base:
for k in override:
if (i.al2000, i.de2000) == (k.al2000, k.de2000):
# found an override
final.append(k)
break
else:
final.append(i)
此解决方案仍然使用嵌套的for循环,但它会从原始解决方案中删除代码重复(迭代overrides
,i
和k
的比较。
答案 1 :(得分:1)
你可以使用字典和一些字典理解。
uniques = {(x.al2000, x.de2000): x for x in base}
uniques.update({(x.al2000, x.de2000): x for x in override})
final = uniques.values()
修改以保留有关在override
中省略额外值的原始行为。
uniques = {(x.al2000, x.de2000): x for x in base}
for value in override:
key = value.al2000, value.de2000
if key in uniques:
uniques[key] = value
# here's the comprehension version, although it's a bit rough on the eyes
# uniques.update({(x.al2000, x.de2000): x for x in override if (x.al2000, x.de2000) in uniques})
final = uniques.values()
答案 2 :(得分:0)
因为你真正想做的就是在覆盖中查找一些东西,然后用它来制作一个词典:
od = {(x.al2000, x.de2000): x for x in override}
现在,只需创建结果:
res = [od.get((b.al2000, b.de2000), b) for b in base]
*未经测试,但应该没问题 *为dirn的建议编辑
答案 3 :(得分:0)
这个答案采用了@ acushner的建议来使用dict,这可能是你案件中最自然的方法。要添加它,在处理覆盖时,ChainMap
很有用,在许多情况下是表示数据结构的最自然方式。
from collections import ChainMap
base_dct = {(x.al2000, x.de2000): x for x in base}
override_dct = {(x.al2000, x.de2000): x for x in override}
z = ChainMap(base_dct, override_dct)
# then access:
z.values()
# or:
z[(x.al2000, x.de2000)]
有关ChainMaps的更多信息,请参阅this question。