简体   繁体   English

如何从单独的键和值列表中制作字典?

[英]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'}

Like this:像这样:

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

Voila :-) The pairwise dict constructor and zip function are awesomely useful.瞧 :-) 成对的dict构造函数和zip函数非常有用。

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

Most performant, dict constructor with zip最高性能,带有zipdict构造函数

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))确实需要对dictzip分别进行一次全局查找,但它不会形成任何不必要的中间数据结构,也不需要处理函数应用程序中的本地查找。

Runner-up, dict comprehension:亚军,听写理解:

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

Python 2, ideal for <= 2.6 Python 2,适用于 <= 2.6

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:来自itertoolsizip在 Python 3 中变为zip 。对于 Python 2, izip比 zip 更好(因为它避免了不必要的列表创建),非常适合 2.6 或更低版本:

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

Result for all cases:所有情况的结果:

In all cases:在所有情况下:

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

Explanation:解释:

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 (因为它创建了一个不必要的列表)。

Less performant alternatives:性能较差的替代方案:

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.我希望他们所有人的性能都会降低,当然也不会更差。

Performance review:性能评估:

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似乎是比较性能的不好方法。 Surely mean and/or max 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 个随机数。这听起来确实是一个相当不寻常的用例。最直接的调用将在大型数据集中占主导地位确实是有道理的,如果操作系统我不会感到惊讶考虑到运行该测试需要多长时间,挂起占主导地位,进一步扭曲你的数字。如果你使用meanmax ,我会认为你的结果毫无意义。

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 函数将较长的列表转换。

  • 2018-04-18 2018-04-18

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 中的两个列表中声明字典:

Method #1: Naive Method方法#1:朴素的方法

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}

Method #2: Using dictionary comprehension方法#2:使用字典理解

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}

Method #3: Using zip() with dict() function方法#3:使用 zip() 和 dict() function

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.

相关问题 如何用列表中的键和值分隔空列表创建字典? - How do I create a dictionary with keys from a list and values separate empty lists? 如何从具有唯一键和值作为列表的字典中制作 dataframe? - How to make a dataframe from a dictionary with unique keys and values as lists? 如何从嵌套的字典键和值列表制作多索引数据框? - How to make multiindex dataframe from a nested dictionary keys and lists of values? 如何制作两个单独的列表中每个键具有多个值的字典? - How do I make a dictionary with multiple values per key from two separate lists? 如何从两个列表创建字典,一个列表是键,另一个包含嵌套值? - How can I create a dictionary from two lists, one list is the keys, the other contains nested values? 如何从列表向字典添加键和值 - How to add keys and values to dictionary from lists 如何从字典列表中创建三个单独的值列表,其中每个字典都有三个键 - How to create three separate lists of values from a list of dictionaries where each dictionary has three keys 如何将 3 个列表映射到字典键 - How can I map 3 lists to dictionary keys 如何使字典返回键基于它们的值之和? - How can I make a dictionary return keys based on the sum of their values? 如何将 2 个列表组合成一个字典,其中键可以有多个值? - How to combine 2 lists into a dictionary, where keys can have multiple values?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM