python转换列表字典
l = ["a", "b", "c", "d", "e"]
我想将这个列表转换成一个字典,如:
d = {"a": "b", "c": "d", "e": ""}
所以基本上,平衡是关键,而赔率是价值。 我知道我可以用“非pythonic”的方式来做,比如if语句的for循环,但我相信应该有一个更“pythonic”的方法来完成这个。 所以,我感谢任何帮助:)
使用通常的石斑鱼配方 ,你可以做:
Python 2:
d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))
Python 3:
d = dict(itertools.zip_longest(*[iter(l)] * 2, fillvalue=""))
如果你还在想什么! 你不会一个人,其实并不那么复杂,让我解释一下。
如何仅使用内置函数将列表转换为字典
我们想把下面的列表变成一个字典,使用奇数条目(从1开始)作为映射到它们连续的偶数条目的关键字。
l = ["a", "b", "c", "d", "e"]
字典()
要创build一个字典,我们可以使用内置的dict
function的映射types按照手册支持以下方法。
dict(one=1, two=2) dict({'one': 1, 'two': 2}) dict(zip(('one', 'two'), (1, 2))) dict([['two', 2], ['one', 1]])
最后一个选项build议我们提供一个带有2个值或(key, value)
元组的列表,所以我们想把我们的顺序列表变成:
l = [["a", "b"], ["c", "d"], ["e",]]
我们还介绍了zip
函数,这是手册解释的内置函数之一 :
返回一个元组列表,其中第i个元组包含每个参数的第i个元素
换句话说,如果我们可以将我们的列表变成两个列表a, c, e
和b, d
那么zip
将完成剩下的工作。
切片符号
我们看到用于string的切片 ,还有主要使用范围或短切片符号的List部分 ,但是这是长切片符号的样子,我们可以用step来完成:
>>> 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'}
尽pipe这是理解所涉及的机制的最简单的方法,但是由于片每次都是新的列表对象,所以存在不足,正如可以看到的克隆示例:
>>> a = [1, 2, 3] >>> b = a >>> b [1, 2, 3] >>> b is a True >>> b = a[:] >>> b [1, 2, 3] >>> b is a False
尽pipeb看起来像是一个,但是现在它们是两个单独的对象,这就是为什么我们更喜欢使用石斑鱼配方 。
石斑鱼食谱
虽然石斑鱼被解释为itertools模块的一部分,但它的基本function也完全正常。
一些严重的伏都教吧? =)但实际上只不过是一些糖的香料,石斑鱼配方是由下面的expression式完成。
*[iter(l)]*2
如果这是有道理的,那么它或多或less会转换成包含在列表中的相同迭代器的两个参数。 让我们分解一下,以帮助解决一些问题。
邮编最短
>>> 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获取一个键,然后每次使用相同的迭代器来完成我们所做的操作,然后返回一个值和一个键和一个值切片更有成效。
你会完成很多与以下哪个进行更小的什么? 因素也许。
>>> it = iter(l) >>> dict(zip(it, it)) {'a': 'b', 'c': 'd'}
如果你注意到所有的例子都没有,那么空键是什么?因为zip
select了最短的两个参数,所以我们该怎么做。
那么一种解决scheme可能是将一个空值添加到奇数长度的列表中,你可以select使用append
和if
语句,尽pipe有点无聊,对吧?
>>> if len(l) % 2: ... l.append("") >>> l ['a', 'b', 'c', 'd', 'e', ''] >>> dict(zip(*[iter(l)]*2)) {'a': 'b', 'c': 'd', 'e': ''}
现在,在你摆脱from itertools import izip_longest
typesfrom itertools import izip_longest
你可能会惊讶地发现它不是必需的,我们可以完成同样的,甚至更好的恕我直言,单独的内置function。
地图最长
我更喜欢使用map()函数而不是izip_longest() ,它不仅使用较短的语法,而且不需要导入,但可以根据需要自动分配一个实际的None
空值。
>>> 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万条logging为基准。
$ 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万条。
$ 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
一无所获! =)
的nJoy!
我会去recursion:
l = ['a', 'b', 'c', 'd', 'e', ' '] d = dict([(k, v) for k,v in zip (l[::2], l[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)))