사전의 값으로 키를 어떻게 교환합니까?


97

사전을 입력으로 받고 키가 입력 값이되고 값이 해당 입력 키가되는 사전을 반환하고 싶습니다. 값은 고유합니다.

예를 들어, 내 입력은 다음과 같습니다.

a = dict()
a['one']=1
a['two']=2

내 출력은 다음과 같습니다.

{1: 'one', 2: 'two'}

명확히하기 위해 내 결과가 다음과 동일하기를 바랍니다.

res = dict()
res[1] = 'one'
res[2] = 'two'

이것을 달성하는 깔끔한 Pythonic 방법이 있습니까?


1
Python 3을 사용하는 경우 좋은 대답이있는 동일한 질문에 대해서는 stackoverflow.com/questions/1087694/… 를 참조하십시오.
Stephen Edmonds

@Stephen : 두 번째로 많이 득표 한 답변을 확인하세요. 연결 한 질문에서 수락 한 답변과 동일합니다. 군중은 다른 답변을 선호했습니다 ...
Roee Adler

4
파이썬은 펄이 아니고, 파이썬은 루비가 아닙니다. 가독성이 중요합니다. 희소가 조밀 한 것보다 낫습니다. 이 점을 감안할 때 이러한 답변의 모든 방법은 나쁘다 ™; 질문에있는 것이 가장 좋은 방법입니다.
o0 '.

답변:


148

파이썬 2 :

res = dict((v,k) for k,v in a.iteritems())

Python 3 (@erik에게 감사) :

res = dict((v,k) for k,v in a.items())

14
이것이 올바른 것처럼 보이지만 코드가 아닌 작동 방식에 대한 설명을 추가하는 것이 정말 좋습니다.

4
값이 고유하지 않으면 어떻게됩니까? 그러면 키는 목록이어야합니다 ... 예 : d = { 'a': 3, 'b': 2, 'c': 2} {v : k for k, v in d.iteritems ()} { 2 : 'b', 3 : 'a'}는 {2 : [ 'b', 'c'], 3 : 'a'}
이어야합니다.

4
@HananShteingart : OP의 질문에 명시된 값은 고유합니다. 귀하의 사례에 대한 별도의 질문 게시물을 작성하십시오 (다른 사람을 위해 여기에 링크하는 것이 좋습니다).
liori

python2 코드가 작동하지만 목록 이해에 []. 목록 이해는 [및 필요하지 ]않습니까?
Trevor Boyd Smith

@TrevorBoydSmith : 이것은 목록 이해력이 아니며 생성기 표현식 입니다.
liori

55
new_dict = dict(zip(my_dict.values(), my_dict.keys()))

4
정말로 values ​​()와 keys ()가 동일한 순서를 갖도록 보장됩니까?
Lennart Regebro

1
yes, from python.org/dev/peps/pep-3106 사양은 항목이 .keys (), .values ​​() 및 .items ()에 의해 반환되는 순서가 동일 함을 의미합니다 (Python에서와 동일). 2.x), 순서는 모두 dict 반복자 (아마도 임의적이지만 dict가 수정되지 않는 한 안정적 임)에서 파생되기 때문입니다. 그러나이 대답은 my_dict를 두 번 호출해야합니다 (하나는 값, 하나는 키). 이것은 이상적이지 않을 수도 있습니다.
sunqiang

4
예,이 답변은 dict를 두 번 반복합니다. sunqiang의 답변은 한 번의 반복 만 필요하므로 큰 사전에 적합합니다.
Carl Meyer

@Carl Meyer : 동의합니다. 또한 그는 큰 데이터 세트에 훨씬 더 나은 itertools를 사용하고 있습니다. 마지막 dict () 호출도 스트리밍인지, 아니면 전체 쌍 목록을 먼저 조합하는지 궁금합니다
Javier

@CarlMeyer 추가로 n> 1e6 (또는 1e9)의 경우 메모리 사용량도 정말 커질 것입니다.
Trevor Boyd Smith

47

3.0 이상을 포함하여 Python 2.7부터는 더 짧고 읽기 쉬운 버전이 있습니다.

>>> my_dict = {'x':1, 'y':2, 'z':3}
>>> {v: k for k, v in my_dict.items()}
{1: 'x', 2: 'y', 3: 'z'}

30
In [1]: my_dict = {'x':1, 'y':2, 'z':3}

In [2]: dict((value, key) for key, value in my_dict.iteritems())
Out[2]: {1: 'x', 2: 'y', 3: 'z'}

3
원래 질문이 아니라 원래 사전에 중복 값이 ​​있고 키 / 값을이 방법으로 바꾸면 어떻게 될지 궁금합니다.
Andre Miller

2
@Andre Miller : 특정 키의 마지막 발생을 취합니다. dict (((1,3), (1,2))) == {1 : 2}
balpha

2
중복은 마지막으로 발생한 복제로 덮어 씁니다.
Christopher

2
@Andre Miller : d.items ()는 임의의 순서로 항목을 반환하기 때문에 중복 값에 대한 임의의 키를 얻습니다.
Ants Aasma

나는 그것이 발견 한 마지막 키, 값 쌍을 취할 것이라고 생각합니다. a [ 'x'] = 3. 그런 다음 a [ 'x'] = 4를 설정합니다.
riza


18

시도해 볼 수 있습니다.

d={'one':1,'two':2}
d2=dict((value,key) for key,value in d.iteritems())
d2
  {'two': 2, 'one': 1}

다음과 같은 경우 사전을 '반전'할 수 없습니다.

  1. 둘 이상의 키가 동일한 값을 공유합니다. 예를 들면 {'one':1,'two':1}. 새 사전에는 키가있는 항목이 하나만있을 수 있습니다 1.
  2. 하나 이상의 값은 해시 할 수 없습니다. 예를 들면 {'one':[1]}. [1]은 유효한 값이지만 유효한 키가 아닙니다.

주제에 대한 토론은 파이썬 메일 링리스트 에서이 스레드 를 참조하십시오 .


또한 원래 dict의 값이 고유한지 확인하는 메모에 대해 +1하십시오. 그렇지 않으면 'reversed'dict에서 덮어 쓰게 될 것입니다. 그리고 이것은 (방금 내 비용으로 이것을 찾았습니다) 코드에서 까다로운 버그를 일으킬 수 있습니다!
monojohnny 2011

15

res = dict(zip(a.values(), a.keys()))


4
dict는 values ​​() 및 keys ()가 동일한 순서로 요소를 반환한다고 보장하지 않습니다. 또한 keys (), values ​​() 및 zip ()은 반복기로 충분할 경우 목록을 반환합니다.
liori 2009-06-23

19
@liori : 당신이 틀렸어요. dict는 values ​​()와 keys ()에 대한 호출 사이의 dict를 수정하지 않는 경우 values ​​()와 keys ()가 동일한 순서에 있음을 보장합니다. 문서에 다음과 같이 명시되어 있습니다. ( "Note"부분 읽기 : docs.python.org/library/stdtypes.html#dict.items ) "If items (), keys (), values ​​(), iteritems (), iterkeys ( ) 및 itervalues ​​()가 사전에 개입하지 않고 호출되면 목록이 직접 대응됩니다. "
nosklo

1
좋아, 그럼 내가 틀렸어. 온라인 문서를 확인하지 않았어. 지적 해주셔서 감사합니다.
liori 2009-06-23

이 답변을 더 효율적으로 만들기 위해 zip 대신 itertools.izip을 사용할 수 있습니다.
Alasdair 2009-06-23

그리고 iterkeys와 itervalues. 그러나 단지뿐만 아니라 iteritems ()를 사용할 수 있습니다
nosklo

15

현재 선행 답변은 값이 고유하다고 가정하지만 항상 그런 것은 아닙니다. 값이 고유하지 않으면 어떻게됩니까? 정보를 잃어 버릴 것입니다! 예를 들면 :

d = {'a':3, 'b': 2, 'c': 2} 
{v:k for k,v in d.iteritems()} 

를 반환합니다 {2: 'b', 3: 'a'}.

에 대한 정보 'c'는 완전히 무시되었습니다. 이상적으로는 {2: ['b','c'], 3: ['a']}. 이것이 하단 구현이하는 일입니다.

Python 2.x

def reverse_non_unique_mapping(d):
    dinv = {}
    for k, v in d.iteritems():
        if v in dinv:
            dinv[v].append(k)
        else:
            dinv[v] = [k]
    return dinv

Python 3.x

def reverse_non_unique_mapping(d):
    dinv = {}
    for k, v in d.items():
        if v in dinv:
            dinv[v].append(k)
        else:
            dinv[v] = [k]
    return dinv

보다 일반적인 경우를 다루기 때문에 정답이어야합니다
Leon Rai

감사합니다! 다른 솔루션에서 정보가 손실되었습니다.

14
new_dict = dict( (my_dict[k], k) for k in my_dict)

또는 더 좋지만 Python 3에서만 작동합니다.

new_dict = { my_dict[k]: k for k in my_dict}

2
실제로 Dict Comprehensions ( PEP 274 )는 Python 2.7에서도 작동합니다.
Arseny 2013

10

Ilya Prokin 의 응답 을 확장하는 또 다른 방법 은 실제로 reversed함수를 사용하는 것입니다.

dict(map(reversed, my_dict.items()))

본질적으로 딕셔너리는 .items()각 항목이 키 / 값 쌍이고 해당 항목이 reversed함수 로 교체되는 곳을 통해 반복됩니다 (사용 ) . 이것이 dict생성자에 전달되면 원하는 값 / 키 쌍으로 변환됩니다.


6

Javier 답변 개선을위한 제안 :

dict(zip(d.values(),d))

이터레이터로 딕셔너리를 살펴보면 관련 딕셔너리의 키를 반환하기 때문에 대신 d.keys()그냥 쓸 수 있습니다 d.

전의. 이 동작에 대해 :

d = {'a':1,'b':2}
for k in d:
 k
'a'
'b'


2
dict(map(lambda x: x[::-1], YourDict.items()))

.items()의 튜플 목록을 반환합니다 (key, value). map()목록의 요소를 통과 lambda x:[::-1]하고 각 요소 (튜플)에 적용하여 반전하므로 각 튜플은 (value, key)맵에서 튀어 나온 새 목록에 포함됩니다. 마지막으로 dict()새 목록에서 사전을 만듭니다.


.items ()는 튜플 (키, 값) 목록을 반환합니다. map ()은 목록의 요소를 통과 lambda x:[::-1]하고 각 요소 (튜플)에 적용하여 반전하므로 각 튜플은 맵에서 튀어 나온 새 목록에서 (값, 키)가됩니다. 마지막으로 dict ()는 새 목록에서 dict를 만듭니다.
Ilya Prokin 2015 년

1

루프 사용 :-

newdict = {} #Will contain reversed key:value pairs.

for key, value in zip(my_dict.keys(), my_dict.values()):
    # Operations on key/value can also be performed.
    newdict[value] = key

1

Python3을 사용하는 경우 약간 다릅니다.

res = dict((v,k) for k,v in a.items())

1

현재 위치 솔루션 추가 :

>>> d = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> for k in list(d.keys()):
...     d[d.pop(k)] = k
... 
>>> d
{'two': 2, 'one': 1, 'four': 4, 'three': 3}

Python3에서는 키 보기 를 반환 list(d.keys())하므로 사용하는 것이 중요 합니다. Python2를 사용하는 경우 충분합니다.dict.keysd.keys()


1

Hanan의 대답은 더 일반적인 경우를 다루기 때문에 올바른 대답입니다 (다른 대답은 중복 상황을 알지 못하는 사람에게 일종의 오해의 소지가 있습니다). Hanan의 대답에 대한 개선은 setdefault를 사용하는 것입니다.

mydict = {1:a, 2:a, 3:b}   
result = {}
for i in mydict:  
   result.setdefault(mydict[i],[]).append(i)
print(result)
>>> result = {a:[1,2], b:[3]}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.