두 목록을 사전으로 변환


1227

당신이 가지고 있다고 상상해보십시오 :

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

다음 사전을 만드는 가장 간단한 방법은 무엇입니까?

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

답변:


2141

이처럼 :

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

Voila :-) pairwise dict생성자와 zip함수는 매우 유용합니다 : https://docs.python.org/3/library/functions.html#func-dict


3
dictionary = {zip(keys, values)}작동하지 않는다는 점은 주목할 가치가 있습니다. 다음과 같이 명시 적으로 선언해야합니다.dict(...)
Fernando Wittmann

5
@FernandoWittmann, 왜 그렇게 기대하는지 모르겠습니다. 하나의 요소를 포함하는 {thing}구문 설탕 set()이다. 여러 요소를 포함하는 {*iterable}구문 설탕 set이다. {k:v}또는 {**mapping} 구성 dict하지만 구문 적으로는 상당히 다릅니다.
Dan Lenski

6
의견 Dan에 감사드립니다. 네 말이 맞아 나는 보통 {}사전에 sintax 를 사용하기 때문에 혼란이 생겼 습니다. 실제로, 우리가 시도 type({})하면 출력은 dict입니다. 그러나 실제로 시도 type({thing})하면 출력은 set입니다.
페르난도 비트 만

우리가보다 잘 할 수 있도록 여기에 왔습니다 {k:v for k, v in zip(keys, values)}. 우리가 할 수있는 것으로 밝혀졌습니다. +1.
JG

139

당신이 가지고 있다고 상상해보십시오 :

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

다음 사전을 생성하는 가장 간단한 방법은 무엇입니까?

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

성능이 가장 뛰어난 dict생성자zip

new_dict = dict(zip(keys, values))

Python 3에서 zip은 이제 lazy iterator를 반환하며 이것이 가장 성능이 좋은 방법입니다.

dict(zip(keys, values))dictzip에 대한 일회성 전역 조회가 각각 필요 하지만 불필요한 중간 데이터 구조를 형성하지 않거나 함수 애플리케이션에서 로컬 조회를 처리해야합니다.

준우승, 독해 :

dict 생성자를 사용하는 데 가장 근접한 것은 dict 이해의 기본 구문을 사용하는 것입니다 ( 다른 사람들이 실수로 말한 것처럼 목록 이해가 아님 ).

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

키 또는 값을 기준으로 매핑하거나 필터링해야 할 때이 옵션을 선택하십시오.

Python 2에서는 zip불필요한 목록을 만들지 않으려면 목록을 반환하고 izip대신 사용하십시오 (zip으로 별칭을 지정하면 Python 3으로 이동할 때 코드 변경을 줄일 수 있습니다).

from itertools import izip as zip

따라서 여전히 (2.7)입니다.

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

파이썬 2, <= 2.6에 이상적

izipfrom itertoolszipPython 3 izip이 됩니다 . 불필요한 목록 생성을 피하기 때문에 Python 2의 zip보다 낫고 2.6 이하에 이상적입니다.

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

파이썬 3은 zip단순히 반복 가능한 객체를 만듭니다.

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

불필요한 데이터 구조를 만드는 것을 피하고 싶기 때문에, 파이썬 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 iterable 위에 배치되고 목록 이해의 경우 추가 목록이 불필요하게 작성됩니다. 나는 그들 모두 성능이 떨어질 것이라고 기대할 것입니다.

성능 검토 :

Ubuntu 16.04에서 Nix가 제공하는 64 비트 Python 3.8.2에서 가장 빠른 것부터 가장 느린 것까지 순서 :

>>> 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성능을 비교하는 나쁜 방법 인 것 같습니다. 확실히 mean및 / 또는 max실제 사용에 대한 훨씬 더 유용한 지표가 될 것입니다.

min이러한 알고리즘은 결정론 적이므로 사용 합니다. 최상의 조건에서 알고리즘의 성능을 알고 싶습니다.

어떤 이유로 든 운영 체제가 중단되면 비교하려는 것과 아무런 관련이 없으므로 이러한 유형의 결과를 분석에서 제외해야합니다.

를 사용 mean하면 이러한 종류의 이벤트가 결과를 크게 왜곡하고 사용 max하면 가장 극단적 인 결과 만 얻을 수 있습니다.

논평자는 또한 말합니다 :

python 3.6.8에서 평균 값을 사용하면 작은 목록의 경우 dict 이해력이 여전히 약 30 % 빠릅니다. 더 큰 목록 (10k 난수)의 경우 dict통화가 약 10 % 빠릅니다.

dict(zip(...10k의 난수를 의미한다고 가정 합니다. 그것은 꽤 특이한 사용 사례처럼 들립니다. 가장 직접적인 호출은 큰 데이터 세트에서 지배적이며, OS 테스트가 해당 테스트를 실행하는 데 걸리는 시간이 오래 걸리고 숫자가 더 치우친 경우 놀라지 않을 것입니다. 그리고 당신이 사용하는 경우 mean또는 max나는 결과의 의미를 고려할 것입니다.

우리의 주요 예에서보다 현실적인 크기를 사용합시다.

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

그리고 우리 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

1
2019 년 중반 (python 3.7.3)부터 다른 타이밍을 찾습니다. %% timeit는 1.57 \ pm 0.019microsec dict(zip(headList, textList))및 1.95 \ pm 0.030 microsec를 반환 합니다 {k: v for k, v in zip(headList, textList)}. 나는 가독성과 속도에 대해 전자를 제안 할 것이다. 분명히 이것은 timeit에 대한 min () vs mean () 인수에 도달합니다.
Mark_Anderson

1
min성능을 비교하는 나쁜 방법 인 것 같습니다. 확실히 mean및 / 또는 max실제 사용에 대한 훨씬 더 유용한 지표가 될 것입니다.
naught101

1
python 3.6.8에서 평균 값을 사용하면 작은 목록의 경우 dict 이해력이 여전히 약 30 % 빠릅니다. 더 큰 목록 (10k 난수)의 경우 dict통화가 약 10 % 빠릅니다.
naught101

@ naught101-나는 당신의 의견을 대답했습니다.
Aaron Hall

3
10k 숫자는 2 개의 긴 고유 요소 목록을 생성하는 빠른 방법 일뿐입니다. 리스트 생성은 타이밍 추정치 외부에서 수행되었습니다. / / 왜 평균 또는 최대가 쓸모 없다고 생각합니까? 이 작업을 여러 번 수행하는 경우 평균 시간은 ~ n * 평균이며 상한은 ~ n * max입니다. 최소값은 하한을 제공하지만 대부분의 사람들은 평균 또는 최악의 성능에 관심을 갖습니다. 차이가 크면 최소값은 대부분의 경우를 대표하지 않습니다. 실제 시나리오에서 최소값이 어떻게 더 의미가 있습니까?
naught101

128

이 시도:

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


18
Python2에서는 사실이지만 Python 3에서는 zip이미 메모리 소비가 경제적입니다. docs.python.org/3/library/functions.html#zip 사실, 당신은 것을 볼 수 있습니다 six사용 zip파이썬 3에서 교체 itertools.izip파이썬 2 pythonhosted.org/six .
Pedro Cattori

35
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}

28

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

17

보다 자연스러운 방법은 사전 이해력을 사용하는 것입니다

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

언젠가는 가장 빠른 방법이고 언젠가 dict는 객체 로 변환하는 것이 가장 느 립니다. 왜 그렇게됩니까?, 고마워 친구.
Haritsinh Gohil


10

Python 3.x를 사용하면 독해력을 발휘합니다.

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

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

print(dic)

dict comprehensions 에 대한 자세한 내용은 여기 에 있습니다.

>>> print {i : chr(65+i) for i in range(4)}
    {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}

8

간단한 코드가 필요하고 익숙하지 않은 사람들을 위해 zip:

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

한 줄의 코드로 수행 할 수 있습니다.

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

6
List1List2
Jean-François Fabre

@ Jean-FrançoisFabre 정말 중요한가? 사전을 만들기 위해 길이가 다른 두 목록을 가져야하는 이유는 무엇입니까?
loved.by.Jesus

아마도 아닙니다, 그러나 이것은 for n in range(len(List1))반 패턴입니다
Jean-François Fabre

3
  • 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')

2

아래 코드에서 사용할 수 있습니다.

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

그러나 목록의 길이가 동일해야합니다. 길이가 같지 않으면 zip 함수가 더 길어집니다.


2

그래프 관련 문제를 해결하는 동안이 의심이있었습니다. 내가 가진 문제는 빈 인접 목록을 정의해야하고 빈 목록으로 모든 노드를 초기화하고 싶었습니다. 즉, 충분히 빠르지 여부를 확인하는 방법을 생각했을 때 지퍼 작업을 수행 할 가치가 있는지 여부를 의미합니다 단순한 할당 키-값 쌍이 아닙니다. 대부분의 시간 후에, 시간 요소는 중요한 쇄빙선입니다. 그래서 두 가지 방법 모두에 대해 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 단계의 단축 접근 방식에 걸린 시간을 능가합니다.


1

다음은 사전에 목록 값을 추가하는 예입니다.

list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)

항상 "Key"(list1)가 항상 첫 번째 매개 변수에 있는지 확인하십시오.

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}

0

열거 형 사전 이해 솔루션 :

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

열거와 루프에 대한 솔루션 :

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

0

두 목록의 조합 인 하나의 목록으로 시도해 볼 수도 있습니다.)

a = [1,2,3,4]
n = [5,6,7,8]

x = []
for i in a,n:
    x.append(i)

print(dict(zip(x[0], x[1])))

-1

우편 기능이없는 방법

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

안녕하세요, 입력 (l1 및 l2)은 목록이어야합니다. l1 및 l2를 세트로 지정하면 삽입 순서가 유지되지 않을 수 있습니다. 나를 위해 나는 출력을 {1 : 'a', 2 : 'c', 3 : 'd', 4 : 'b', 5 : 'e'}로
얻었다
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.