python convert list to dictionary
1 | l = ["a","b","c","d","e"] |
我要将此列表转换为如下字典:
1 | d = {"a":"b","c":"d","e":""} |
号
所以基本上,均等是关键,而概率是价值。我知道我可以用一种"非Python式"的方式来完成,比如用if语句的for循环,但是我相信应该有一种更"Python式"的方式来完成这一点。所以,我感谢你的帮助:)
如果你还在想什么呢!你不会孤单的,其实并不那么复杂,我来解释一下。
如何仅使用内置函数将列表转换为字典我们要将下面的列表转换成一个字典,使用奇数条目(从1开始计数)作为映射到其连续偶数条目的键。
1 | l = ["a","b","c","d","e"] |
()
为了创建字典,我们可以根据手册使用内置的
1 2 3 4 | dict(one=1, two=2) dict({'one': 1, 'two': 2}) dict(zip(('one', 'two'), (1, 2))) dict([['two', 2], ['one', 1]]) |
。
最后一个选项建议我们提供一个列表,其中包含2个值或
1 | l = [["a","b"], ["c","d"], ["e",]] |
。
我们还介绍了
returns a list of tuples, where the i-th tuple contains the i-th element from each of the arguments
号
换言之,如果我们可以将我们的列表分为两个列表:
我们看到的切片与字符串一起使用,在主要使用范围或短切片表示法的列表部分也有进一步介绍,但这就是长切片表示法的外观,以及我们可以通过步骤完成的工作:
1 2 3 4 5 6 7 8 9 10 11 | >>> l[::2] ['a', 'c', 'e'] >>> l[1::2] ['b', 'd'] >>> zip(['a', 'c', 'e'], ['b', 'd']) [('a', 'b'), ('c', 'd')] >>> dict(zip(l[::2], l[1::2])) {'a': 'b', 'c': 'd'} |
尽管这是理解所涉及机制的最简单方法,但也有一个缺点,因为切片每次都是新的列表对象,如下面的克隆示例所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> a = [1, 2, 3] >>> b = a >>> b [1, 2, 3] >>> b is a True >>> b = a[:] >>> b [1, 2, 3] >>> b is a False |
。
尽管b看起来像a,但现在它们是两个独立的对象,这就是为什么我们更喜欢使用grouper配方。
石斑鱼食谱虽然grouper被解释为itertools模块的一部分,但它也可以很好地与基本功能配合使用。
一些严重的巫毒对吧?=)但实际上,对于香料来说,仅仅是一点语法糖,石斑鱼的食谱是通过以下表达式完成的。
1 | *[iter(l)]*2 |
如果这有任何意义的话,它或多或少地转换为包装在列表中的同一迭代器的两个参数。让我们把它分解来帮助散光。
拉链最短1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | >>> l*2 ['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e'] >>> [l]*2 [['a', 'b', 'c', 'd', 'e'], ['a', 'b', 'c', 'd', 'e']] >>> [iter(l)]*2 [<listiterator object at 0x100486450>, <listiterator object at 0x100486450>] >>> zip([iter(l)]*2) [(<listiterator object at 0x1004865d0>,),(<listiterator object at 0x1004865d0>,)] >>> zip(*[iter(l)]*2) [('a', 'b'), ('c', 'd')] >>> dict(zip(*[iter(l)]*2)) {'a': 'b', 'c': 'd'} |
。
正如您所看到的,两个迭代器的地址保持不变,因此我们使用相同的迭代器,zip首先从中获取一个键,然后在每次单步执行相同的迭代器时获取一个值、一个键和一个值,以更有效地完成切片的工作。
你将完成非常多相同的以下内容,其中携带一个较小的什么?可能是因素。
1 2 3 | >>> it = iter(l) >>> dict(zip(it, it)) {'a': 'b', 'c': 'd'} |
号
如果你注意到在所有的例子中都没有空键
好吧,一个解决方案可能是在奇数长度的列表中添加一个空值,您可以选择使用
1 2 3 4 5 6 7 8 | >>> if len(l) % 2: ... l.append("") >>> l ['a', 'b', 'c', 'd', 'e', ''] >>> dict(zip(*[iter(l)]*2)) {'a': 'b', 'c': 'd', 'e': ''} |
号
现在,在您耸耸肩去使用
我更喜欢使用map()函数而不是izip_longer(),它不仅使用较短的语法,不需要导入,而且可以在需要时自动分配实际的
1 2 3 4 5 6 | >>> l = ["a","b","c","d","e"] >>> l ['a', 'b', 'c', 'd', 'e'] >>> dict(map(None, *[iter(l)]*2)) {'a': 'b', 'c': 'd', 'e': None} |
号
通过对比Kursedmetal所指出的两种方法的性能,可以清楚地看出,ITertools模块在大容量上远远优于map函数,这是与1000万条记录相比的基准。
1 2 3 4 5 6 7 8 | $ time python -c 'dict(map(None, *[iter(range(10000000))]*2))' real 0m3.755s user 0m2.815s sys 0m0.869s $ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(10000000))]*2, fillvalue=None))' real 0m2.102s user 0m1.451s sys 0m0.539s |
号
然而,导入该模块的成本会对较小的数据集造成一定的影响,当这些数据集开始直接到达时,映射返回的速度要快得多,高达10万条记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $ time python -c 'dict(map(None, *[iter(range(100))]*2))' real 0m0.046s user 0m0.029s sys 0m0.015s $ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100))]*2, fillvalue=None))' real 0m0.067s user 0m0.042s sys 0m0.021s $ time python -c 'dict(map(None, *[iter(range(100000))]*2))' real 0m0.074s user 0m0.050s sys 0m0.022s $ time python -c 'from itertools import izip_longest; dict(izip_longest(*[iter(range(100000))]*2, fillvalue=None))' real 0m0.075s user 0m0.047s sys 0m0.024s |
号
什么也看不到!=)
尼乔!
使用通常的石斑鱼食谱,您可以做到:
Python2:
1 | d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue="")) |
Python3:
1 | d = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue="")) |
号
我将使用递归:
1 2 | l = ['a', 'b', 'c', 'd', 'e', ' '] d = dict([(k, v) for k,v in zip (l[::2], l[1::2])]) |
。
不确定它是否会帮助您,但它对我有用:
1 2 | l = ["a","b","c","d","e"] outRes = dict((l[i], l[i+1]) if i+1 < len(l) else (l[i], '') for i in xrange(len(l))) |