将[key1,val1,key2,val2]转换为字典?

231
假如我有一个Python的列表a,其中的元素方便地映射到一个字典。每个偶数元素代表字典的键,而接下来的奇数元素则是值。
例如:
a = ['hello','world','1','2']

我希望将其转换为字典b,其中

b['hello'] = 'world'
b['1'] = '2'

如何以语法最清晰的方式完成这个任务?


4
可能与使用Python从列表创建字典重复。 - Jeru Luke
12个回答

307
b = dict(zip(a[::2], a[1::2]))
如果a很大,你可能想要像下面这样做,不像上面那样创建任何临时列表。
from itertools import izip
i = iter(a)
b = dict(izip(i, i))
在Python 3中,您还可以使用字典推导式,但具有讽刺意味的是,我认为最简单的方法是使用range()len(),这通常会被视为代码异味。
b = {a[i]: a[i+1] for i in range(0, len(a), 2)}

因此,在Python 3中,iter()/izip()方法仍然是最符合Python风格的方法,虽然正如EOL在评论中指出的,zip()在Python 3中已经是lazy的了,所以你不需要使用izip()

i = iter(a)
b = dict(zip(i, i))

在Python 3.8及更高版本中,你可以使用“海象”运算符 (:=) 将其写成一行代码:

b = dict(zip(i := iter(a), i))
否则,您需要使用分号将其放在一行上。

10
在Python 3中,您可以使用zip()函数来创建迭代器,因此您可以使用zip(i, i)来简化代码。 - Eric O. Lebigot
5
请注意,Python 2.7.3也具有字典推导式。 - user1438003
或者像这样简单的代码 ({'abc': a, 'def' : b} for a, b in zip(list1, list2)) - optimists

69

简单回答

另一种选项(由Alex Martelli提供 - 来源):

dict(x[i:i+2] for i in range(0, len(x), 2))

相关说明

如果您遇到这种情况:

a = ['bi','double','duo','two']

你希望得到这个(列表中的每个元素都将给定值(在本例中为2)作为键):

{'bi':2,'double':2,'duo':2,'two':2}

您可以使用:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}

2
这只适用于Python 3吗? - Tagar
3
使用 fromkeys 方法。{'bi': 2, 'double': 2, 'duo': 2, 'two': 2}其中 fromkeys 是一个方法,用于创建一个新的字典,并将其所有键的值设置为给定的参数(在本例中为数字2)。 - Gdogg
2
这个正在做的事情与问题所要求的不同。 - ozn
由于某种原因,dict.fromkeys() 使每个键的值重复(就像我提供的项目都“链接”或指向内存中的同一位置)。 尝试:a = dict.fromkeys(['op1', 'op2'], {}) 然后 a["op1"] = 3,你会发现 a["op2"] 也被填充了。 - Ricky Levi

19
你可以很容易地使用字典推导式来实现这个功能:
a = ['hello','world','1','2']

my_dict = {item : a[index+1] for index, item in enumerate(a) if index % 2 == 0}

这相当于下面的for循环:

my_dict = {}
for index, item in enumerate(a):
    if index % 2 == 0:
        my_dict[item] = a[index+1]

17

我发现很酷的一件事情是,如果你的列表只有两个项目:

ls = ['a', 'b']
dict([ls])
>>> {'a':'b'}

记住,字典接受包含一个可迭代项的可迭代项,其中每个可迭代项本身必须是恰好具有两个对象的可迭代项。


简单易懂,如果列表包含两个以上的项目,则使用dict(ls)而不是dict([ls])。例如,如果ls=['a', 'b', 'c', 'd'],则使用dict(ls)。 - ankit tyagi
2
优美而简洁。这里的关键是:“可迭代对象中的每个元素本身必须是一个恰好有两个对象的可迭代对象。” - Abhijeet
这真的值得更多的赞,上面一半的答案都是相同的,只是说要使用zip... - Mark

5

可能不是最符合Python风格的写法,但

>>> b = {}
>>> for i in range(0, len(a), 2):
        b[a[i]] = a[i+1]

10
阅读有关 enumerate 的内容。 - SilentGhost
5
enumerate 不能指定步长,但可以使用 for i, key in enumerate(a[::2]): 来达到相同的效果。但这种方法并不符合 Python 的编程风格,因为字典构造函数可以为您完成大部分工作。 - John La Rooy
@SilentGhost,gnibbler:非常感谢你们拓宽了我的视野!我将尽可能在未来加以应用! - sahhhm
@gnibbler:你能详细解释一下 for i, key in enumerate(a[::2]): 这种方法是如何工作的吗?得到的键值对将是 0 hello1 1,但我不清楚如何使用它们来生成 {'hello':'world', '1':'2'} - martineau
1
@martineau,你是正确的。我想我应该是指 enumerate(a)[::2] - John La Rooy

4

您可以快速完成而不需要创建额外的数组,因此即使是非常大的数组也可以使用此方法:

dict(izip(*([iter(a)]*2)))

如果你有一个生成器a,那就更好了:

dict(izip(*([a]*2)))

以下是简要概述:
iter(h)    #create an iterator from the array, no copies here
[]*2       #creates an array with two copies of the same iterator, the trick
izip(*())  #consumes the two iterators creating a tuple
dict()     #puts the tuples into key,value of the dictionary

这将创建一个具有相等键和值对的字典 ({'hello':'hello','world':'world','1':'1','2':'2'})。 - mik
不,一切都正常。请仔细阅读。它说:“如果您有一个生成器...”如果您没有生成器,只需使用第一行。第二行是一个替代方案,如果您有一个生成器而不是列表,那么它将非常有用,因为大多数情况下都是这样。 - topkara

1
你也可以像这样做(在此处进行字符串到列表的转换,然后转换为字典)
    string_list = """
    Hello World
    Goodbye Night
    Great Day
    Final Sunset
    """.split()

    string_list = dict(zip(string_list[::2],string_list[1::2]))

    print string_list

1

我也非常希望能够有一个一句话的转换代码,因为这样的列表在Perl中是哈希的默认初始化器。

本主题给出了异常全面的答案-

我的方式(我是Python新手),使用Python 2.7生成器表达式

dict((a[i], a[i + 1]) for i in range(0, len(a) - 1, 2))


0

你也可以尝试这种方法,将键和值保存在不同的列表中,然后使用字典方法。

data=['test1', '1', 'test2', '2', 'test3', '3', 'test4', '4']

keys=[]
values=[]
for i,j in enumerate(data):
    if i%2==0:
        keys.append(j)
    else:
        values.append(j)

print(dict(zip(keys,values)))

输出:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}

0

我不确定这是否符合Python的风格,但似乎可以工作

def alternate_list(a):
   return a[::2], a[1::2]

key_list,value_list = alternate_list(a)
b = dict(zip(key_list,value_list))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接