从单独的键和值列表中创建字典 (dict)

Make a dictionary (dict) from separate lists of keys and values

提问人:Guido 提问时间:10/17/2008 最后编辑:cottontailGuido 更新时间:11/17/2023 访问量:1276691

问:

我想结合这些:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

合并到一个词典中:

{'name': 'Monty', 'age': 42, 'food': 'spam'}

我该怎么做?

python 列表 字典

评论


答:

2896赞 Dan Lenski 10/17/2008 #1

喜欢这个:

keys = ['a', 'b', 'c']
values = [1, 2, 3]
dictionary = dict(zip(keys, values))
print(dictionary) # {'a': 1, 'b': 2, 'c': 3}

瞧:-)成对的 dict 构造函数和 zip 函数非常有用。

评论

29赞 Fernando Wittmann 8/28/2019
值得注意的是,这是行不通的。您必须显式声明为dictionary = {zip(keys, values)}dict(...)
29赞 Dan Lenski 8/29/2019
不知道你为什么会期望它,@FernandoWittmann。 是句法糖来构造一个包含一个元素的。 是句法糖来构造包含多个元素的 a。 或者构造一个 ,但这在语法上是截然不同的。{thing}set(){*iterable}set{k:v}{**mapping}dict
14赞 Fernando Wittmann 8/29/2019
谢谢你的评论丹。你是对的。我的困惑是因为我通常使用sintax作为词典。事实上,如果我们尝试,输出是 .但实际上,如果我们尝试,那么输出是 .{}type({})dicttype({thing})set
21赞 J.G. 1/23/2020
我来这里是为了万一我们能做得更好。事实证明我们可以。+1.{k:v for k, v in zip(keys, values)}
4赞 Peter Mortensen 6/2/2022
meta 正在讨论此答案的修订版。
41赞 iny 10/17/2008 #2
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
out = dict(zip(keys, values))

输出:

{'food': 'spam', 'age': 42, 'name': 'Monty'}
138赞 Mike Davis 10/17/2008 #3

试试这个:

>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}

在 Python 2 中,与 相比,它在内存消耗方面也更经济。zip

评论

23赞 Pedro Cattori 2/17/2017
对于 Python2 为 True,但在 Python 3 中,内存消耗已经很经济了。docs.python.org/3/library/functions.html#zip事实上,你可以看到在 Python 3 中使用来替换 Python 2 pythonhosted.org/sixzipsixzipitertools.izip
0赞 Jules Gagnon-Marchand 8/25/2022
已弃用的答案
16赞 jfs 10/17/2008 #4

如果需要在创建字典之前转换键或值,则可以使用生成器表达式。例:

>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3])) 

看一看像 pythonista 一样的代码:惯用的 Python

31赞 Brendan Berg 6/11/2012 #5

您还可以在 Python ≥ 2.7 中使用字典推导式:

>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}
11赞 exploitprotocol 3/30/2013 #6

对于那些需要简单代码但不熟悉以下方面的人:zip

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

这可以通过一行代码来完成:

d = {List1[n]: List2[n] for n in range(len(List1))}

评论

7赞 Jean-François Fabre 9/13/2017
如果时间长于List1List2
0赞 loved.by.Jesus 12/18/2019
@Jean-FrançoisFabre 这很重要吗?为什么我们应该用两个不同长度的列表来构建一个字典?
1赞 Jean-François Fabre 12/18/2019
可能不是,但在此之后是一种反模式for n in range(len(List1))
15赞 kiriloff 5/25/2013 #7

使用 Python 3.x,进行字典推导

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in zip(keys, values)}

print(dic)

有关字典推导的更多信息,这里有一个示例:

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
21赞 Polla A. Fattah 11/16/2015 #8

一种更自然的方法是使用字典理解

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')    
dict = {keys[i]: values[i] for i in range(len(keys))}

评论

0赞 Haritsinh Gohil 8/8/2019
有时它是最快的方法,有时它是最慢的转换为对象,为什么会这样?,谢谢伙计。dict
238赞 Russia Must Remove Putin 11/16/2015 #9

想象一下,您有:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

生成以下词典的最简单方法是什么?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

性能最强,构造函数dictzip

new_dict = dict(zip(keys, values))

在 Python 3 中,zip 现在返回一个惰性迭代器,这是现在性能最高的方法。

dict(zip(keys, values))确实需要对 和 进行一次性全局查找,但它不会形成任何不必要的中间数据结构,也不必处理函数应用程序中的本地查找。dictzip

亚军,词典理解:

使用 dict 构造函数的一个紧随其后的方法是使用 dict 推导式的原生语法(而不是其他人错误地认为的列表推导式):

new_dict = {k: v for k, v in zip(keys, values)}

当您需要根据键或值进行映射或筛选时,请选择此选项。

在 Python 2 中,返回一个列表,为避免创建不必要的列表,请改用(别名为 zip 可以减少迁移到 Python 3 时的代码更改)。zipizip

from itertools import izip as zip

所以这仍然是(2.7):

new_dict = {k: v for k, v in zip(keys, values)}

Python 2,非常适合 <= 2.6

izip从 成为 Python 3 中。 比 Python 2 的 zip 更好(因为它避免了不必要的列表创建),非常适合 2.6 或更低版本:itertoolszipizip

from itertools import izip
new_dict = dict(izip(keys, values))

所有病例的结果:

在所有情况下:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

解释:

如果我们看一下帮助,我们会看到它需要各种形式的参数:dict


>>> help(dict)

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized with the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)

最佳方法是使用可迭代对象,同时避免创建不必要的数据结构。在 Python 2 中,zip 创建了一个不必要的列表:

>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

在 Python 3 中,等效的是:

>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

而 Python 3 只是创建了一个可迭代的对象:zip

>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>

由于我们希望避免创建不必要的数据结构,因此我们通常希望避免使用 Python 2(因为它会创建不必要的列表)。zip

性能较差的替代方案:

这是传递给 dict 构造函数的生成器表达式:

generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)

或同等学历:

dict((k, v) for k, v in zip(keys, values))

这是传递给 dict 构造函数的列表推导式:

dict([(k, v) for k, v in zip(keys, values)])

在前两种情况下,在 zip 可迭代对象上放置了一个额外的非操作性(因此不必要的)计算层,而在列表推导的情况下,不必要地创建了一个额外的列表。我希望它们都表现不佳,当然也不会更高。

绩效考核:

在 Nix 提供的 64 位 Python 3.8.2 中,在 Ubuntu 16.04 上,从最快到最慢的顺序是:

>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>> 
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583

dict(zip(keys, values))即使使用较小的键和值集也会获胜,但对于较大的集合,性能差异会变得更大。

一位评论者说:

min似乎是比较性能的糟糕方法。当然和/或对于实际使用来说会更有用。meanmax

我们之所以使用这些算法,是因为这些算法是确定性的。我们想知道算法在最佳条件下的性能。min

如果操作系统因任何原因挂起,则与我们尝试比较的内容无关,因此我们需要从分析中排除这些结果。

如果我们使用 ,这类事件会极大地扭曲我们的结果,如果我们使用,我们只会得到最极端的结果——最有可能受到此类事件影响的结果。meanmax

一位评论者还说:

在 python 3.6.8 中,使用平均值,字典理解确实更快,对于这些小列表来说,大约提高了 30%。对于较大的列表(10k 随机数),调用速度大约快 10%。dict

我想我们的意思是 10k 随机数。这听起来确实是一个相当不寻常的用例。最直接的调用在大型数据集中占主导地位确实是有道理的,如果操作系统挂起占主导地位,考虑到运行该测试需要多长时间,我不会感到惊讶,这进一步扭曲了你的数字。如果你使用,或者我会认为你的结果毫无意义。dict(zip(...meanmax

让我们在顶部示例中使用更实际的尺寸:

import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))

我们在这里看到,对于较大的数据集,确实运行速度快了大约 20%。dict(zip(...

>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095

评论

2赞 Mark_Anderson 7/2/2019
截至 2019 年年中(python 3.7.3),我发现时间不同。%%time它返回 1.57 \pm 0.019 微秒,返回 & 1.95 \pm 0.030 微秒。我建议前者具有可读性和速度。显然,这涉及到了 timeit 的 min() 与 mean() 参数。dict(zip(headList, textList)){k: v for k, v in zip(headList, textList)}
0赞 Loisaida Sam Sandberg 4/8/2020
你似乎在说词典理解速度最快,但在性能评估中,看起来更快。也许你忘了更新一些东西?dict(zip(keys, values))
1赞 ShadowRanger 10/30/2020
次要说明(鉴于 Python 2 EOL,基本上无关紧要):您可以将其用作替代方法,以更明确地描述导入,以将 Python 3 作为常规的替代品。它完全等同于清楚( 本身只是 的别名)。from future_builtins import zipfrom itertools import izip as zipzipzipfuture_builtins.zipitertools.izip
-1赞 xiyurui 5/24/2017 #10

不带 zip 函数的方法

l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
    for l2_ in l2:
        d1[l1_] = l2_
        l2.remove(l2_)
        break  

print (d1)


{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}

评论

0赞 Noordeen 1/31/2019
嗨,xiyurui,输入(l1 和 l2)应该是一个列表。如果将 l1 和 l2 指定为一组,则可能无法保留广告顺序。对我来说,我得到的输出是{1:'A',2:'C',3:'D',4:'B',5:'e'}
3赞 Akash Nayak 11/16/2017 #11

您可以使用以下代码:

dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))

但是请确保列表的长度相同,如果长度不相同,则zip函数将转为较长的列表。

4赞 Wizard 4/18/2018 #12
  • 2018-04-18

最好的解决方案仍然是:

In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...: 

In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}

转置它:

    lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
    keys, values = zip(*lst)
    In [101]: keys
    Out[101]: ('name', 'age', 'food')
    In [102]: values
    Out[102]: ('Monty', 42, 'spam')
7赞 Cyd 2/20/2019 #13

下面也是在字典中添加列表值的示例:

listKey = ["Name", "Surname", "Age"]
listValue = [["Cyd", "Lendl", "Leal"], ["Surname1", "Surname2", "Surname3"], [21, 32, 47]]
dic = dict(zip(listKey , listValue ))
print(dic)

始终确保您的 “Key”(listKey) 始终位于 dict 的第一个参数中。

对于字典中的单个值

singleKey = ["Name", "Surname", "Age"]
singleValue = ["Cyd"], ["Surname1"], [21]
dic = dict(zip(singleKey , singleValue ))
print(dic)

始终确保您的 “Key”(singleKey ) 始终位于 dict 的第一个参数中。

列表的输出如下

{
'Name': ['Cyd', 'Lendl', 'Leal'], 
'Surname': ['Surname1', 'Surname2', 'Surname3'], 
'Age': [21, 32, 47]
}

单值的输出

{
'Name': ['Cyd'], 
'Surname': ['Surname1'], 
'Age': [21]
}
4赞 Mayank Prakash 7/20/2019 #14

当我试图解决一个与图形相关的问题时,我有这个疑问。我遇到的问题是我需要定义一个空的邻接列表,并想用一个空列表初始化所有节点,这时我想到我检查它是否足够快,我的意思是是否值得做一个 zip 操作而不是简单的赋值键值对。毕竟,大多数时候,时间因素是一个重要的破冰船。因此,我对这两种方法都执行了 timeit 操作。

import timeit
def dictionary_creation(n_nodes):
    dummy_dict = dict()
    for node in range(n_nodes):
        dummy_dict[node] = []
    return dummy_dict


def dictionary_creation_1(n_nodes):
    keys = list(range(n_nodes))
    values = [[] for i in range(n_nodes)]
    graph = dict(zip(keys, values))
    return graph


def wrapper(func, *args, **kwargs):
    def wrapped():
        return func(*args, **kwargs)
    return wrapped

iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)

for trail in range(1, 8):
    print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')

对于n_nodes = 10,000,000 我明白了,

迭代: 2.825081646999024 速记:3.535717916001886

迭代: 5.051560923002398 速记:6.255070794999483

迭代: 6.52859034499852 速记:8.221581164998497

迭代: 8.683652416999394 速记:12.599181543999293

迭代: 11.587241565001023 速记:15.27298851100204

迭代: 14.816342867001367 速记:17.162912737003353

迭代: 16.645022411001264 速记:19.976680120998935

您可以清楚地看到,在某个点之后,n_th步的迭代方法超过了 n 步速记方法所花费的时间1_th。

0赞 jay123 11/5/2019 #15

使用枚举作为字典推导的解决方案:

dict = {item : values[index] for index, item in enumerate(keys)}

带有枚举的循环解决方案:

dict = {}
for index, item in enumerate(keys):
    dict[item] = values[index]
-1赞 Franco 8/28/2020 #16

虽然有多种方法可以做到这一点,但我认为最基本的方法是处理它;创建循环和字典,并将值存储到该字典中。在递归方法中,这个想法仍然是一样的,但函数没有使用循环,而是调用自己,直到它到达终点。当然,还有其他方法,如使用等,这些都不是最有效的解决方案。dict(zip(key, value))

y = [1,2,3,4]
x = ["a","b","c","d"]

# This below is a brute force method
obj = {}
for i in range(len(y)):
    obj[y[i]] = x[i]
print(obj)

# Recursive approach 
obj = {}
def map_two_lists(a,b,j=0):
    if j < len(a):
        obj[b[j]] = a[j]
        j +=1
        map_two_lists(a, b, j)
        return obj
      


res = map_two_lists(x,y)
print(res)

两个结果都应打印出来

{1: 'a', 2: 'b', 3: 'c', 4: 'd'}  
1赞 DonkeyKong 12/16/2020 #17

如果您正在处理 1 组以上的值,并且希望有一个字典列表,您可以使用以下命令:

def as_dict_list(data: list, columns: list):
    return [dict((zip(columns, row))) for row in data]

实际示例是数据库查询中的元组列表与来自同一查询的列元组配对。其他答案仅提供 1 对 1。

评论

0赞 Woodman 12/6/2022
zip() 调用周围用双括号有什么原因吗?
0赞 DonkeyKong 12/20/2022
@Woodman好问题。我不知道。从这里的代码来看,它似乎过多了。
0赞 Zeinab Mardi 3/4/2021 #18
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
dic = {}
c = 0
for i in keys:
    dic[i] = values[c]
    c += 1

print(dic)
{'name': 'Monty', 'age': 42, 'food': 'spam'}
1赞 J.Jai 5/18/2022 #19

可以通过以下方式完成。

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam'] 

dict = {}

for i in range(len(keys)):
    dict[keys[i]] = values[i]
    
print(dict)

{'name': 'Monty', 'age': 42, 'food': 'spam'}
1赞 guest 11/21/2022 #20

所有答案总结如下:

l = [1, 5, 8, 9]
ll = [3, 7, 10, 11]

邮编

dict(zip(l,ll)) # {1: 3, 5: 7, 8: 10, 9: 11}

#if you want to play with key or value @recommended

{k:v*10 for k, v in zip(l, ll)} #{1: 30, 5: 70, 8: 100, 9: 110}

计数器

d = {}
c=0
for k in l:
    d[k] = ll[c] #setting up keys from the second list values
    c += 1
print(d)
{1: 3, 5: 7, 8: 10, 9: 11}

枚举

d = {}
for i,k in enumerate(l):
    d[k] = ll[i]
print(d)
{1: 3, 5: 7, 8: 10, 9: 11}
0赞 Soudipta Dutta 12/5/2022 #21
import pprint

p = ['A', 'B', 'C']
q = [5, 2, 7]
r = ["M", "F", "M"]
s = ['Sovabazaar','Shyambazaar','Bagbazaar','Hatkhola']


def makeDictUsingAlternateLists1(**rest):
    print("*rest.keys() : ",*rest.keys())
    print("rest.keys() : ",rest.keys())
    print("*rest.values() : ",*rest.values())
    print("**rest.keys() : ",rest.keys())
    print("**rest.values() : ",rest.values())
    [print(a) for a in zip(*rest.values())]
    
    [ print(dict(zip(rest.keys(),a))) for a in zip(*rest.values())]
    print("...")
    
    
    finalRes= [ dict( zip( rest.keys(),a))  for a in zip(*rest.values())] 
    return finalRes
    
l = makeDictUsingAlternateLists1(p=p,q=q,r=r,s=s)
pprint.pprint(l)    
"""
*rest.keys() :  p q r s
rest.keys() :  dict_keys(['p', 'q', 'r', 's'])
*rest.values() :  ['A', 'B', 'C'] [5, 2, 7] ['M', 'F', 'M'] ['Sovabazaar', 'Shyambazaar', 'Bagbazaar', 'Hatkhola']
**rest.keys() :  dict_keys(['p', 'q', 'r', 's'])
**rest.values() :  dict_values([['A', 'B', 'C'], [5, 2, 7], ['M', 'F', 'M'], ['Sovabazaar', 'Shyambazaar', 'Bagbazaar', 'Hatkhola']])
('A', 5, 'M', 'Sovabazaar')
('B', 2, 'F', 'Shyambazaar')
('C', 7, 'M', 'Bagbazaar')
{'p': 'A', 'q': 5, 'r': 'M', 's': 'Sovabazaar'}
{'p': 'B', 'q': 2, 'r': 'F', 's': 'Shyambazaar'}
{'p': 'C', 'q': 7, 'r': 'M', 's': 'Bagbazaar'}
...
[{'p': 'A', 'q': 5, 'r': 'M', 's': 'Sovabazaar'},
 {'p': 'B', 'q': 2, 'r': 'F', 's': 'Shyambazaar'},
 {'p': 'C', 'q': 7, 'r': 'M', 's': 'Bagbazaar'}]
 
"""
0赞 cottontail 11/17/2023 #22

这里的大多数答案都提到使用每个 和 列表中的一个项目创建元组。只要列表的长度相同,这就可以正常工作。如果列表的长度不同,则在较短的列表中停止;从而忽略较长列表中的其余元素。以下示例说明了这一点:zip()keysvalues

keys = ['name', 'age', 'food']
values = ['Monty', 42]
dict(zip(keys, values))                    # {'name': 'Monty', 'age': 42}

如果不希望出现这种行为,则标准库中存在类似的方法,该方法会创建一个迭代器,该迭代器会迭代,直到较长的列表用尽为止。默认情况下,缺失值填充为 None。itertools.zip_longest

from itertools import zip_longest
dict(zip_longest(keys, values))            # {'name': 'Monty', 'age': 42, 'food': None}

它还接受 kwarg,可用于指定要为缺失值填写的内容。fillvalue=

dict(zip_longest(keys, values, fillvalue='spam')) # {'name': 'Monty', 'age': 42, 'food': 'spam'}

请注意,如果两个列表的长度相同,并生成相同的输出:zip()itertools.zip_longest()

keys = values = range(5)
dict(zip(keys, values)) == dict(zip_longest(keys, values))                       # True
{k:v for k,v in zip(keys, values)} == {k:v for k,v in zip_longest(keys, values)} # True