从这些列表中,
lst1 = ['a','b','c']
lst2 = [[1,2],[3,4,5],[6,7]]
我想创造:
{1: 'a', 3: 'b', 6: 'c', 2: 'a', 4: 'b', 7: 'c', 5: 'b'}
我可以使用 for 循环创建它:
d = {}
for l, nums in zip(lst1, lst2):
for num in nums:
d[num] = l
我想我需要使用地图和邮政编码,所以我尝试了,
dict(map(lambda x: dict(x), zip(lst2,lst1)))
但这给出了
ValueError: dictionary update sequence element #1 has length 1; 2 is required.
我认为问题是
lst2
是一个列表列表,但我只是不知道如何继续。
使用理解:
d = {num:l for l, nums in zip(lst1, lst2) for num in nums}
由于存在嵌套循环,因此您需要一些东西来扩展第二个列表。简单:)
如果你更喜欢聪明而不是简单,还有另一种方法:
collections.ChainMap( *itertools.starmap( dict.fromkeys, zip(lst2, lst1)))
其工作方式是,
zip(lst2, lst1)
的每个元素都是一个元组,其中键列表作为第一个值,并将所有这些键分配给第二个值。这正是 dict.fromkeys
所期望的格式
>>> it = zip(lst2, lst1)
>>> x = next(it)
>>> x
([1, 2], 'a')
>>> dict.fromkeys(*x)
{1: 'a', 2: 'a'}
itertools.starmap
将其应用于 zip 的每个元素,这为我们提供了部分字典的列表:
>>> list(itertools.starmap(dict.fromkeys, zip(lst2, lst1)))
[{1: 'a', 2: 'a'}, {3: 'b', 4: 'b', 5: 'b'}, {6: 'c', 7: 'c'}]
collections.ChainMap
,它本身可以用作字典,但如果您确实需要将其折叠为单个字典,则可以将其传递给 dict
构造函数:
>>> dict(collections.ChainMap(*itertools.starmap(dict.fromkeys, zip(lst2, lst1))))
{6: 'c', 7: 'c', 3: 'b', 4: 'b', 5: 'b', 1: 'a', 2: 'a'}
编辑:
您的预期输出与循环产生的输出不同。如果您想在一个班轮中获得预期的输出(当然不包括进口),这是一种解决方案。
(i) 基于 @mozway 使用
itertools.zip_longest
创建跨子列表的元组 zip 对象的想法,使用 dict.fromkeys
方法从这些元组和 lst1
、 创建字典
(ii) 使用
map
和字典理解,从 (i) 创建字典列表
(iii) 使用
functools.reduce
,将列表扁平化为单个字典
from itertools import zip_longest
from functools import reduce
out = reduce(lambda d, x: {**d, **x}, map(lambda kv: {k:v for k,v in zip(*kv) if k is not None}, dict.fromkeys(zip_longest(*lst2), lst1).items()))
另一个解决方案:
from itertools import zip_longest, starmap
from functools import reduce
out = dict(reduce(lambda tp, x: tp+tuple(filter(None, x)), zip_longest(*map(dict.items, starmap(dict.fromkeys, zip(lst2, lst1))))))
输出:
{1: 'a', 3: 'b', 6: 'c', 2: 'a', 4: 'b', 7: 'c', 5: 'b'}
旧解决方案(如果顺序无关紧要):
正如您所说,问题在于
lst1
是一个列表,而 lst2
是列表的列表。我们可以使用另一个 zip 从 lst1
创建子列表。然后使用 functools.reduce
展平字典列表:
from functools import reduce
out = reduce(lambda d, x: {**d, **x},
map(lambda x: dict(zip(x[0], [x[1]]*len(x[0]))), zip(lst2,lst1)))
或者使用@Tadhg的出色建议来使用
itertools.starmap
和 dict.fromkeys
方法,你也可以这样做:
from itertools import starmap
out = reduce(lambda d,x: {**d, **x}, starmap(dict.fromkeys, zip(lst2,lst1)))
或使用
collections.ChainMap
(更简单):
from collections import ChainMap
out = ChainMap(*starmap(dict.fromkeys, zip(lst2,lst1)))
输出:
{1: 'a', 2: 'a', 3: 'b', 4: 'b', 5: 'b', 6: 'c', 7: 'c'}
为了好玩,只是一个具有字典理解的变体(类似于@Tadhg已经提出的),但保留子列表索引的顺序:
from itertools import zip_longest
out = {k: v for v, *keys in zip_longest(lst1, *lst2)
for k in keys if k is not None}
输出:
{1: 'a', 3: 'a', 6: 'a', 2: 'b', 4: 'b', 7: 'b', 5: 'c'}