我有两个不同的词典列表(ListA和ListB)。
listA中的所有词典都有字段" id"和" external_id" listB中的所有字典都有字段" num"和" external_num"
我需要获取所有字典对,其中external_id
= num
的值和external_num
= id
的值。
我可以使用此代码实现这一目标:
for dictA in ListA:
for dictB in ListB:
if dictA["id"] == dictB["external_num"] and dictA["external_id"] == dictB["num"]:
但是我看到了许多漂亮的python表达式,我想有可能让这个结果更加pythonic风格,不是吗?
我喜欢:
res = [A, B for A, B in listA, listB if A['id'] == B['extnum'] and A['ext'] == B['num']]
答案 0 :(得分:3)
你非常接近,但是你并没有告诉Python你想如何连接这两个列表以获得字典对A
和B
。
如果您想将ListA
中的所有词典与ListB
中的所有词典进行比较,则需要itertools.product
:
from itertools import product
res = [A, B for A, B in product(ListA, ListB) if ...]
或者,如果您希望对具有相同的索引,请使用zip
:
res = [A, B for A, B in zip(ListA, ListB) if ...]
如果您不想立即构建整个列表,请注意您可以使用itertools.ifilter
选择所需的对:
from itertools import ifilter, product
for A, B in ifilter(lambda (A, B): ...,
product(ListA, ListB)):
# do whatever you want with A and B
(如果您使用zip
执行此操作,请改用itertools.izip
以最大限度地提高效果。)
关于Python 3.x的注释:
zip
和filter
no longer return lists因此itertools.izip
和itertools.ifilter
不再存在(正如range
推出xrange
}),您只需要product
中的itertools
;和lambda (A, B):
是no longer valid syntax;你需要编写过滤函数来获取单个元组参数lambda t:
,例如将A
替换为t[0]
。答案 1 :(得分:1)
首先,为了代码清晰,我实际上可能会选择你的第一个选项 - 在这种情况下,我不认为使用for
循环特别是非Pythonic。但是,如果您想尝试使用列表推导,有几点需要注意:
列表推导返回的每个项目都只需要一个单项。尝试返回A, B
会给你一个SyntaxError
。但是,您可以返回列表或元组(或其他任何内容,即单个对象),因此res = [(A,B) for...]
之类的内容将开始工作。
另一个问题是你是如何迭代这些列表的 - 从你的第一段代码开始,看起来你没有对这些列表排队做出任何假设,这意味着:如果你的第二项似乎没问题{1}}与listA
中的第14项匹配,只要它们在相应字段上匹配即可。这是完全合理的,但请注意,无论您如何尝试,都需要两个listB
循环*。你仍然需要你的比较。因此,作为列表理解,您可以尝试:
for
然后,在res = [(A, B) for A in listA for B in listB if A['id']==B['extnum'] and A['extid']==B['num']]
中,您将拥有0个或更多元组,每个元组将包含您感兴趣的相应字典。要使用它们:
res
或更简洁(和Python):
for tup in res:
A = tup[0]
B = tup[1]
#....
因为Python非常聪明,知道它产生了一个包含2个元素的项目(元组),所以它可以直接将它们分配给for A,B in res:
#...
和A
。
编辑:*回想起来,你需要两个B
循环并不完全正确,如果你的列表足够大,那么制作一个中间字典可能会有所帮助。这样:
for
并且,如果# make a dictionary with key=tuple, value=dictionary
interim = {(A['id'], A['extid']): A for A in listA}
for B in listB:
tup = (B['extnum'], B['num']) ## order matters! match-up with A
if tup in interim:
A = interim[tup]
print(A, B)
- id
对不希望在listA中的所有项目中都是唯一的,那么您需要使用extid
来查看collections.defaultdict
......但我不确定这仍然适合“更多Pythonic”类别。
我意识到这对你提出的问题可能有些过分,但我不能让我的'list
循环声明成立,因为它并不完全正确。