我需要创建一个列表解析,从列表中的列表中的字典中提取值,到目前为止我的尝试都让我失望。该对象如下所示:
MyList=[[{'animal':'A','color':'blue'},{'animal':'B','color':'red'}],[{'animal':'C','color':'blue'},{'animal':'D','color':'Y'}]]
我想提取dict / list / list中每个元素的值,以便获得两个新列表:
Animals=[[A,B],[C,D]]
Colors=[[blue,red],[blue,Y]]
有什么建议吗?不一定需要使用列表理解;到目前为止,这只是我的起点。谢谢!
答案 0 :(得分:5)
Animals = [[d['animal'] for d in sub] for sub in MyList]
Colors = [[d['color'] for d in sub] for sub in MyList]
给出了理想的结果:
[['A', 'B'], ['C', 'D']]
[['blue', 'red'], ['blue', 'Y']] # No second 'red'.
我在这里做的是获取每个子列表,然后是每个字典,然后访问正确的密钥。
答案 1 :(得分:1)
在单个作业中(使用单个列表理解,以及map
和zip
的帮助):
Colors, Animals = map(list,
zip(*[map(list,
zip(*[(d['color'], d['animal']) for d in a]))
for a in MyList]))
如果您对元组没问题,可以避免两次调用map =>列表
修改强>:
通过分解嵌套理解,让我们在一些细节中看到它。
我们还假设MyList
有m
个元素,共有n
个对象(字典)。
[[d for d in sub] for sub in MyList]
这将迭代子列表中的每个字典。对于它们中的每一个,我们在第一个元素中创建一个具有color
属性的对象,在第二个元素中创建其animal
属性:
(d['color'], d['animal'])
到目前为止,这需要时间与O(n)
成比例 - 将处理完整的n
元素。
print [[(d['color'], d['animal']) for d in sub] for sub in MyList]
现在,对于原始列表的每个m
子列表,我们有一个我们需要解压缩的夫妇列表,即将其转换为两个单例列表。在Python中,使用zip
函数执行 unzip ,方法是将可变数量的元组作为参数传递(第一个元组的arity确定它输出的元组数)。例如,通过3对夫妇,我们得到两个每个3个元素的列表
>>> zip((1,2), (3,4), (5,6)) #Prints [(1, 3, 5), (2, 4, 6)]
要将此应用于我们的案例,我们需要将一对夫妇传递给zip
作为可变数量的参数:使用 splat 运算符完成,即{ {3}}
[zip(*[(d['color'], d['animal']) for d in sub]) for sub in MyList]
此操作需要遍历每个子列表一次,然后遍历我们在上一步中创建的每个子对。因此,总运行时间为O(n + n + m)
= O(n)
,并且近似2*n + 2*m
次操作。
到目前为止,我们有m
个子列表,每个子列表包含两个元组(第一个将收集子列表的所有颜色,第二个收集所有动物的颜色)。要获得两个每个m
个元组的列表,我们再次应用解压缩
zip(*[zip(*[(d['color'], d['animal']) for d in sub]) for sub in MyList]
这将需要额外的m
步骤 - 因此,运行时间将保持O(n)
,并进行近似2*n + 4*m
次操作。
为了简单起见,我们在此分析中省略了将元组映射到列表 - 如果您对元组没有问题,那就没问题了。
然而,元组是不可变的,所以情况可能并非如此。
如果您需要列表列表,则需要将list
函数应用于每个元组:每个m
子列表(总共2*n
个元素)一次,每个元素一次2个第一级列表,即动物和颜色,(每个都有m
个元素)。假设list
需要的时间与应用序列的长度成比例,此额外步骤需要2*n + 2*m
次操作,这仍然是O(n)
。