python将列表转换为字典

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"]

()

为了创建字典,我们可以根据手册使用内置的dict函数来映射类型,支持以下方法。

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个值或(key, value)元组,因此我们希望将顺序列表转换为:

1
l = [["a","b"], ["c","d"], ["e",]]

我们还介绍了zip功能,这是本手册解释的内置功能之一:

returns a list of tuples, where the i-th tuple contains the i-th element from each of the arguments

换言之,如果我们可以将我们的列表分为两个列表:a, c, eb, d,那么zip将完成其余的操作。

切片表示法

我们看到的切片与字符串一起使用,在主要使用范围或短切片表示法的列表部分也有进一步介绍,但这就是长切片表示法的外观,以及我们可以通过步骤完成的工作:

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'}

如果你注意到在所有的例子中都没有空键e,这是因为zip选择了两个参数中最短的一个,那么我们该怎么做呢?

好吧,一个解决方案可能是在奇数长度的列表中添加一个空值,您可以选择使用appendif语句来实现这个技巧,尽管有点无聊,对吧?

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': ''}

现在,在您耸耸肩去使用from itertools import izip_longest类型之前,您可能会惊讶地发现它不是必需的,我们可以单独使用内置功能来完成相同的,甚至更好的imho。

最长的地图

我更喜欢使用map()函数而不是izip_longer(),它不仅使用较短的语法,不需要导入,而且可以在需要时自动分配实际的None空值。

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)))