这是我想要实现的目标:
我有两个词典列表。所有词典都具有以下结构:
dictinary = {'name':'MyName', 'state':'MyState'}
我想浏览两个列表的所有元素,并比较具有相同名称的条目的状态。这是我能想象到的最佳方式:
for d in list1:
name = d['name']
for d2 in list2:
if d2['name'] == name:
if d1['state'] != d2['state']:
# Do something
虽然我认为这种方法可行,但我想知道是否有更高效和/或更优雅的方式来执行此操作。谢谢你的想法!
答案 0 :(得分:2)
从itertools看一下product
:
import itertools
xs = range(1,10)
ys = range(11,20)
zs = itertools.product(xs,ys)
list(zs)
[(1,11),(1,12),(1,13),(1,14),(1,15),(1,16),(1,17),(1,18) ),(1,19),(2,11),(2,12),(2,13),(2,14),(2,15),(2,16),(2,17), (2,18),(2,19),(3,11),(3,12),(3,13),(3,14),(3,15),(3,16),(3) ,17),(3,18),(3,19),(4,11),(4,12),(4,13),(4,14),(4,15),(4,16) ),(4,17),(4,18),(4,19),(5,11),(5,12),(5,13),(5,14),(5,15), (5,16),(5,17),(5,18),(5,19),(6,11),(6,12),(6,13),(6,14),(6) ,15),(6,16),(6,17),(6,18),(6,19),(7,11),(7,12),(7,13),(7,14) ),(7,15),(7,16),(7,17),(7,18),(7,19),(8,11),(8,12),(8,13), (8,14),(8,15),(8,16),(8,17),(8,18),(8,19),(9,11),(9,12),(9) ,13),(9,14),(9,15),(9,16),(9,17),(9,18),(9,19)]
其他一些事情 -
[('name','state'),('name','state'),('name','state')...]
另一种方法是直接比较元素,例如你可以检查setA(dicts列表1)和setB(dicts列表2)的交集
>>> listA = [('fred','A'), ('bob','B'), ('mary', 'D'), ('eve', 'E')]
>>> listB = [('fred','X'), ('clive', 'C'), ('mary', 'D'), ('ben','B')]
# your listA and listB could be sets to begin with
>>> set.intersection(set(listA),set(listB))
set([('mary', 'D')])
然而,这种方法不允许重复......
答案 1 :(得分:1)
我能想到的最优雅的方式是列表理解。
[[do_something() for d1 in list1 if d1["name"] == d2["name"] and d1["state"] != d2["state"]] for d2 in list2]
但那是相同的代码。
您还可以通过减少它来使示例代码更加优雅:
for d in list1:
for d2 in list2:
if d2['name'] == d['name'] and d['state'] != d2['state']:
# Do something
答案 2 :(得分:1)
其他答案是有效的(它们提供了正确的答案),但是对于大型列表不能很好地执行,因为它们使用嵌套迭代 - 对于长度为N的列表,它们使用的步骤数增加如N ^ 2。如果清单很小,这不是一个问题;但如果列表很大,迭代次数就会爆炸。
保持时间复杂度与N呈线性关系的另一种方法就是这样(非常详细):
##
## sample data
data = list()
data.append( [
dict(name='a', state='0'),
dict(name='b', state='1'),
dict(name='c', state='3'),
dict(name='d', state='5'),
dict(name='e', state='7'),
dict(name='f', state='10'),
dict(name='g', state='11'),
dict(name='h', state='13'),
dict(name='i', state='14'),
dict(name='l', state='19'),
])
data.append( [
dict(name='a', state='0'),
dict(name='b', state='1'),
dict(name='c', state='4'),
dict(name='d', state='6'),
dict(name='e', state='8'),
dict(name='f', state='10'),
dict(name='g', state='12'),
dict(name='j', state='16'),
dict(name='k', state='17'),
dict(name='m', state='20'),
])
##
## coalesce lists to a single flat dict for searching
dCombined = {}
for d in data:
dCombined = { i['name'] : i['state'] for i in d }
##
## to record mismatches
names = []
##
## iterate over lists -- individually / not nested
for d in data:
for i in d:
if i['name'] in dCombined and i['state'] != dCombined[i['name']]:
names.append(i['name'])
##
## see result
print names
注意事项:
OP没有说清单中是否有重复的名字;这会改变这种方法。
根据“做某事”的细节,您可能会记录除名称之外的其他内容 - 可以存储对单个dict对象的引用或副本,或者“做某事”所需的任何内容。
这种方法的权衡是它需要比以前的答案更多的内存;但是内存需求只能与实际不匹配的数量相关,而且是O(N)。
注意:
当您有两个以上的列表要比较时,这种方法也有效 - 例如如果有5个列表,我的替代方案仍然是O(N)的时间和记忆,而之前的答案将是O(N ^ 5)及时!