[英]How can I make a dictionary from separate lists of keys and values?
I want to combine these:我想结合这些:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
Into a single dictionary:进入单个字典:
{'name': 'Monty', 'age': 42, 'food': 'spam'}
Imagine that you have:
想象一下,你有:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
What is the simplest way to produce the following dictionary ?
生成以下字典的最简单方法是什么?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
constructor with zip
zip
的dict
构造函数new_dict = dict(zip(keys, values))
In Python 3, zip now returns a lazy iterator, and this is now the most performant approach.在 Python 3 中, zip 现在返回一个惰性迭代器,这是现在性能最高的方法。
dict(zip(keys, values))
does require the one-time global lookup each for dict
and zip
, but it doesn't form any unnecessary intermediate data-structures or have to deal with local lookups in function application. dict(zip(keys, values))
确实需要对dict
和zip
分别进行一次全局查找,但它不会形成任何不必要的中间数据结构,也不需要处理函数应用程序中的本地查找。
A close runner-up to using the dict constructor is to use the native syntax of a dict comprehension (not a list comprehension, as others have mistakenly put it):使用 dict 构造函数的一个接近的亚军是使用 dict 推导式的本机语法(不是列表推导式,因为其他人错误地把它):
new_dict = {k: v for k, v in zip(keys, values)}
Choose this when you need to map or filter based on the keys or value.当您需要根据键或值进行映射或过滤时选择此项。
In Python 2, zip
returns a list, to avoid creating an unnecessary list, use izip
instead (aliased to zip can reduce code changes when you move to Python 3).在 Python 2 中,
zip
返回一个列表,为避免创建不必要的列表,请改用izip
(别名为 zip 可以在迁移到 Python 3 时减少代码更改)。
from itertools import izip as zip
So that is still (2.7):所以仍然是(2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
from itertools
becomes zip
in Python 3. izip
is better than zip for Python 2 (because it avoids the unnecessary list creation), and ideal for 2.6 or below:来自
itertools
的izip
在 Python 3 中变为zip
。对于 Python 2, izip
比 zip 更好(因为它避免了不必要的列表创建),非常适合 2.6 或更低版本:
from itertools import izip
new_dict = dict(izip(keys, values))
In all cases:在所有情况下:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
If we look at the help on dict
we see that it takes a variety of forms of arguments:如果我们查看有关
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)
The optimal approach is to use an iterable while avoiding creating unnecessary data structures.最佳方法是使用可迭代对象,同时避免创建不必要的数据结构。 In Python 2, zip creates an unnecessary list:
在 Python 2 中, zip 创建了一个不必要的列表:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
In Python 3, the equivalent would be:在 Python 3 中,等价于:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
and Python 3's zip
merely creates an iterable object:而 Python 3 的
zip
仅仅创建了一个可迭代对象:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Since we want to avoid creating unnecessary data structures, we usually want to avoid Python 2's zip
(since it creates an unnecessary list).由于我们希望避免创建不必要的数据结构,我们通常希望避免 Python 2 的
zip
(因为它创建了一个不必要的列表)。
This is a generator expression being passed to the dict constructor:这是传递给 dict 构造函数的生成器表达式:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
or equivalently:或等效地:
dict((k, v) for k, v in zip(keys, values))
And this is a list comprehension being passed to the dict constructor:这是传递给 dict 构造函数的列表推导:
dict([(k, v) for k, v in zip(keys, values)])
In the first two cases, an extra layer of non-operative (thus unnecessary) computation is placed over the zip iterable, and in the case of the list comprehension, an extra list is unnecessarily created.在前两种情况下,在 zip 迭代上放置了额外的非操作(因此不必要的)计算层,在列表推导的情况下,不必要地创建了额外的列表。 I would expect all of them to be less performant, and certainly not more-so.
我希望他们所有人的性能都会降低,当然也不会更差。
In 64 bit Python 3.8.2 provided by Nix, on Ubuntu 16.04, ordered from fastest to slowest:在 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))
wins even with small sets of keys and values, but for larger sets, the differences in performance will become greater. dict(zip(keys, values))
即使使用小的键和值集也会获胜,但是对于更大的集,性能差异会变得更大。
A commenter said:一位评论者说:
min
seems like a bad way to compare performance.min
似乎是比较性能的不好方法。 Surelymean
and/ormax
would be much more useful indicators for real usage.当然,
mean
和/或max
对于实际使用来说会是更有用的指标。
We use min
because these algorithms are deterministic.我们使用
min
是因为这些算法是确定性的。 We want to know the performance of the algorithms under the best conditions possible.我们想知道算法在可能的最佳条件下的性能。
If the operating system hangs for any reason, it has nothing to do with what we're trying to compare, so we need to exclude those kinds of results from our analysis.如果操作系统因任何原因挂起,这与我们要比较的内容无关,因此我们需要从分析中排除这些结果。
If we used mean
, those kinds of events would skew our results greatly, and if we used max
we will only get the most extreme result - the one most likely affected by such an event.如果我们使用
mean
,这些类型的事件会极大地扭曲我们的结果,如果我们使用max
我们只会得到最极端的结果——最有可能受到此类事件影响的结果。
A commenter also says:一位评论者还说:
In python 3.6.8, using mean values, the dict comprehension is indeed still faster, by about 30% for these small lists.
在 python 3.6.8 中,使用平均值,dict 理解确实更快,对于这些小列表大约快 30%。 For larger lists (10k random numbers), the
dict
call is about 10% faster.对于较大的列表(10k 个随机数),
dict
调用要快 10%。
I presume we mean dict(zip(...
with 10k random numbers. That does sound like a fairly unusual use case. It does makes sense that the most direct calls would dominate in large datasets, and I wouldn't be surprised if OS hangs are dominating given how long it would take to run that test, further skewing your numbers. And if you use mean
or max
I would consider your results meaningless.我认为我们的意思是
dict(zip(...
带有 10k 个随机数。这听起来确实是一个相当不寻常的用例。最直接的调用将在大型数据集中占主导地位确实是有道理的,如果操作系统我不会感到惊讶考虑到运行该测试需要多长时间,挂起占主导地位,进一步扭曲你的数字。如果你使用mean
或max
,我会认为你的结果毫无意义。
Let's use a more realistic size on our top examples:让我们在上面的例子中使用更真实的尺寸:
import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))
And we see here that dict(zip(...
does indeed run faster for larger datasets by about 20%.我们在这里看到
dict(zip(...
确实对于较大的数据集运行速度快了大约 20%。
>>> 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
Try this:尝试这个:
>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}
In Python 2, it's also more economical in memory consumption compared to zip
.在 Python 2 中,与
zip
相比,它在内存消耗方面也更经济。
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
out = dict(zip(keys, values))
Output:输出:
{'food': 'spam', 'age': 42, 'name': 'Monty'}
You can also use dictionary comprehensions in Python ≥ 2.7:您还可以在 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'}
A more natural way is to use dictionary comprehension更自然的方法是使用字典理解
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dict = {keys[i]: values[i] for i in range(len(keys))}
If you need to transform keys or values before creating a dictionary then a generator expression could be used.如果您需要在创建字典之前转换键或值,则可以使用生成器表达式。 Example:
例子:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Take a look Code Like a Pythonista: Idiomatic Python .看看Code Like a Pythonista:Idiomatic Python 。
with Python 3.x, goes for dict comprehensions使用 Python 3.x,适用于 dict 理解
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dic = {k:v for k,v in zip(keys, values)}
print(dic)
More on dict comprehensions here , an example is there:更多关于dict理解here ,一个例子是:
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
For those who need simple code and aren't familiar with zip
:对于那些需要简单代码且不熟悉
zip
的人:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
This can be done by one line of code:这可以通过一行代码完成:
d = {List1[n]: List2[n] for n in range(len(List1))}
you can use this below code:您可以使用以下代码:
dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))
But make sure that length of the lists will be same.if length is not same.then zip function turncate the longer one.但请确保列表的长度相同。如果长度不同。则 zip 函数将较长的列表转换。
The best solution is still:最好的解决方案仍然是:
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'}
Tranpose it:转置它:
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')
Here is also an example of adding a list value in you dictionary这也是在您的字典中添加列表值的示例
list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)
always make sure the your "Key"(list1) is always in the first parameter.始终确保您的“密钥”(list1)始终位于第一个参数中。
{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
I had this doubt while I was trying to solve a graph-related problem.当我试图解决与图形相关的问题时,我有这个疑问。 The issue I had was I needed to define an empty adjacency list and wanted to initialize all the nodes with an empty list, that's when I thought how about I check if it is fast enough, I mean if it will be worth doing a zip operation rather than simple assignment key-value pair.
我遇到的问题是我需要定义一个空的邻接列表并想用一个空列表初始化所有节点,这就是我想如何检查它是否足够快的时候,我的意思是是否值得进行 zip 操作而不是简单的赋值键值对。 After all most of the times, the time factor is an important ice breaker.
毕竟大多数时候,时间因素是一个重要的破冰者。 So I performed timeit operation for both approaches.
所以我对这两种方法都执行了 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)}')
For n_nodes = 10,000,000 I get,对于 n_nodes = 10,000,000 我得到,
Iteration: 2.825081646999024 Shorthand: 3.535717916001886迭代:2.825081646999024 简写:3.535717916001886
Iteration: 5.051560923002398 Shorthand: 6.255070794999483迭代:5.051560923002398 简写:6.255070794999483
Iteration: 6.52859034499852 Shorthand: 8.221581164998497迭代:6.52859034499852 简写:8.221581164998497
Iteration: 8.683652416999394 Shorthand: 12.599181543999293迭代:8.683652416999394 简写:12.599181543999293
Iteration: 11.587241565001023 Shorthand: 15.27298851100204迭代:11.587241565001023 简写:15.27298851100204
Iteration: 14.816342867001367 Shorthand: 17.162912737003353迭代:14.816342867001367 简写:17.162912737003353
Iteration: 16.645022411001264 Shorthand: 19.976680120998935迭代:16.645022411001264 简写:19.976680120998935
You can clearly see after a certain point, iteration approach at n_th step overtakes the time taken by shorthand approach at n-1_th step.您可以清楚地看到,在某个点之后,第 n_th 步的迭代方法超过了 n-1_th 步的速记方法所花费的时间。
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'}
Solution as dictionary comprehension with enumerate:使用枚举作为字典理解的解决方案:
dict = {item : values[index] for index, item in enumerate(keys)}
Solution as for loop with enumerate:使用枚举的 for 循环解决方案:
dict = {}
for index, item in enumerate(keys):
dict[item] = values[index]
If you are working with more than 1 set of values and wish to have a list of dicts you can use this:如果您正在使用一组以上的值并希望拥有一个dicts 列表,您可以使用它:
def as_dict_list(data: list, columns: list):
return [dict((zip(columns, row))) for row in data]
Real-life example would be a list of tuples from a db query paired to a tuple of columns from the same query.现实生活中的示例是来自 db 查询的元组列表与来自同一查询的列元组配对。 Other answers only provided for 1 to 1.
其他答案仅提供 1 对 1。
It can be done by the following way.可以通过以下方式完成。
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'}
With below methods you can see how to declare a dictionary from two lists in Python:通过以下方法,您可以看到如何从 Python 中的两个列表中声明字典:
The basic method that can be applied to perform this task is the brute force method to achieve this.可用于执行此任务的基本方法是实现此任务的蛮力方法。 For this, simply declare a dictionary, and then run nested loop for both the lists and assign key and value pairs to from list values to dictionary.
为此,只需声明一个字典,然后为两个列表运行嵌套循环,并将键和值对分配给从列表值到字典。
keys = ["A", "B", "C"]
values = [1, 2, 3]
print("Keys list is : ", keys)
print("Values list is : ", values)
dictionary = {}
for key in keys:
for value in values:
dictionary[key] = value
values.remove(value)
break
print ("Expected dictionary is : ", dictionary)
Output:
Output:
Keys list is: ['A', 'B', 'C'] Values list is: [1, 2, 3] Expected dictionary is: {'A': 1, 'B': 2, 'C': 3}
The more concise way to achieve the above method, dictionary comprehension method offers the faster and time-saving approach by reducing the lines to type.实现上述方法的方法越简洁,字典理解方法通过减少输入行数提供了更快、更省时的方法。
keys = ["A", "B", "C"]
values = [1, 2, 3]
print("Keys list is : ", keys)
print ("Values list is : " + str(values))
dictionary = {keys[i]: values[i] for i in range(len(keys))}
print ("Expected dictionary is : " + str(dictionary))
Output:
Output:
Keys list is: ['A', 'B', 'C'] Values list is: [1, 2, 3] Expected dictionary is: {'A': 1, 'B': 2, 'C': 3}
Most pythonic and generic method to perform this very task is by using zip()
.执行此任务的大多数 Pythonic 和通用方法是使用
zip()
。 This function pairs the list element with other list element at corresponding index in form of key-value pairs.此 function 以键值对的形式将列表元素与相应索引处的其他列表元素配对。
keys = ["A", "B", "C"]
values = [1, 2, 3]
print("Keys list is : ", keys)
print ("Values list is : " + str(values))
dictionary = dict(zip(keys, values))
print ("Expected dictionary is : " + str(dictionary))
Output:
Output:
Keys list is: ['A', 'B', 'C'] Values list is: [1, 2, 3] Expected dictionary is: {'A': 1, 'B': 2, 'C': 3}
method without zip function没有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'}
Imagine that you have the following list.假设您有以下列表。
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
What is the simplest way to produce the following dictionary?产生以下字典的最简单方法是什么?
a_dict = {'name': 'Monty', 'age': 42, 'food': 'spam'}
Although there are multiple ways of doing this but i think most fundamental way of approaching it;尽管有多种方法可以做到这一点,但我认为最根本的方法是; creating a loop and dictionary and store values into that dictionary .
创建一个循环和字典并将值存储到该字典中。 In the recursive approach the idea is still same it but instead of using a loop, the function called itself until it reaches to the end.
在递归方法中,想法仍然相同,但不是使用循环,而是函数调用自身,直到它到达末尾。 Of course there are other approaches like using
dict(zip(key, value))
and etc. These aren't the most effective solutions.当然还有其他方法,例如使用
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)
Both the results should print两个结果都应该打印
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.