답변:
Python 2.7.x의 경우
inv_map = {v: k for k, v in my_map.iteritems()}
Python 3+의 경우 :
inv_map = {v: k for k, v in my_map.items()}
The order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon
. 그런 식으로 유지된다는 보장은 없으므로 Dict
와 같은 동작 에 의존하는 코드를 작성하지 마십시오 OrderedDict
.
dict의 값이 고유하다고 가정하면 :
dict((v, k) for k, v in my_map.iteritems())
iteritems()
출력 될 순서에 대한 보증은 없을 것이므로, 임의의 키가 고유하지 않은 값에 대해 어떤 조건에서는 명백히 재현 될 수있는 방식으로 할당되지만 일반적으로는 그렇지 않은 것으로 가정 될 수 있습니다.
iteritems()
메소드 가 없으며이 접근법은 작동하지 않습니다. items()
수락 된 답변에 표시된대로 대신 사용 하십시오. 또한 사전 이해력은이를 호출하는 것보다 더 예쁘게 만듭니다 dict
.
의 값 my_map
이 고유하지 않은 경우 :
inv_map = {}
for k, v in my_map.iteritems():
inv_map[v] = inv_map.get(v, [])
inv_map[v].append(k)
inv_map.get(v, [])
. 이미 추가 된 목록이 있으면 목록을 반환하므로 할당이 빈 목록으로 재설정되지 않습니다. setdefault
그래도 여전히 더 예쁘다.
inv_map.setdefault(v, set()).add(k)
.
my_map.items()
대신 사용하십시오 my_map.iteritems()
.
맵핑 유형을 유지하면서 ( dict
또는 dict
서브 클래스 인 경우) 이를 수행하려면 다음을 수행하십시오 .
def inverse_mapping(f):
return f.__class__(map(reversed, f.items()))
이 시도:
inv_map = dict(zip(my_map.values(), my_map.keys()))
(참고 사전 뷰에 대한 파이썬 문서가 있음을 명시 적으로 보장 .keys()
하고 .values()
작업에 대한 위의 접근을 허용하는 동일한 순서로, 자신의 요소를 가지고있다.)
또는
inv_map = dict((my_map[k], k) for k in my_map)
또는 python 3.0의 dict comprehensions 사용
inv_map = {my_map[k] : k for k in my_map}
더 기능적인 다른 방법 :
my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
filter
및 map
변형 더 성장하지 죽을와 지능형리스트에 포섭 될".
dict
같은 다른 매핑 유형 collections.OrderedDict
또는collections.defaultdict
이것은 Robert 의 대답 에 따라 확장 되어 dict의 값이 고유하지 않은 경우에 적용됩니다.
class ReversibleDict(dict):
def reversed(self):
"""
Return a reversed dict, with common values in the original dict
grouped into a list in the returned dict.
Example:
>>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
>>> d.reversed()
{1: ['d'], 2: ['c', 'b', 'f'], 3: ['a', 'e']}
"""
revdict = {}
for k, v in self.iteritems():
revdict.setdefault(v, []).append(k)
return revdict
구현은 reversed
두 번 사용할 수 없으며 원본을 다시 가져올 수 없다는 제한이 있습니다 . 대칭이 아닙니다. Python 2.6으로 테스트되었습니다. 다음 은 결과 dict을 인쇄하는 데 사용하는 유스 케이스입니다.
당신이 오히려를 사용하는 거라고 경우 set
(A)보다 list
,이 대신에, 의미가있는 정렬되지 않은 응용 프로그램이 존재할 수 setdefault(v, []).append(k)
, 사용 setdefault(v, set()).add(k)
.
revdict.setdefault(v, set()).add(k)
set
입니다. 여기에 적용되는 내장형입니다. 어떤 값이 아닌 어디 모든 키를 찾으려면 1
나 2
? 그럼 난 그냥 할 수 있습니다 d.keys() - inv_d[1] - inv_d[2]
(파이썬 3에서)
다음을 사용하여 중복 키로 사전을 뒤집을 수도 있습니다 defaultdict
.
from collections import Counter, defaultdict
def invert_dict(d):
d_inv = defaultdict(list)
for k, v in d.items():
d_inv[v].append(k)
return d_inv
text = 'aaa bbb ccc ddd aaa bbb ccc aaa'
c = Counter(text.split()) # Counter({'aaa': 3, 'bbb': 2, 'ccc': 2, 'ddd': 1})
dict(invert_dict(c)) # {1: ['ddd'], 2: ['bbb', 'ccc'], 3: ['aaa']}
이 기술은를 사용하는 동등한 기술보다 간단하고 빠릅니다
dict.setdefault()
.
예를 들어 다음과 같은 사전이 있습니다.
dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}
그리고 당신은 그런 거꾸로 된 형태로 그것을 얻고 싶습니다 :
inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}
첫 번째 해결책 . 사전에서 키-값 쌍을 반전 시키려면 for
-loop 접근법을 사용하십시오 .
# Use this code to invert dictionaries that have non-unique values
inverted_dict = dict()
for key, value in dict.items():
inverted_dict.setdefault(value, list()).append(key)
두번째 해결책 . 반전을 위해 사전 이해 접근법을 사용하십시오 .
# Use this code to invert dictionaries that have unique values
inverted_dict = {value: key for key, value in dict.items()}
세 번째 해결책 . 사용 반전 되 돌리는 방법을 (두번째 솔루션에 의존)
# Use this code to invert dictionaries that have lists of values
dict = {value: key for key in inverted_dict for value in my_map[key]}
dict
변수 이름에 예약되어 사용되어서는 안됩니다
my_map
입니다
dictio()
? 당신은 의미 했습니까 dict()
?
목록과 사전 이해의 조합. 중복 키를 처리 할 수 있습니다
{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
값이 고유하지 않고 약간 하드 코어 한 경우 :
inv_map = dict(
(v, [k for (k, xx) in filter(lambda (key, value): value == v, my_map.items())])
for v in set(my_map.values())
)
특히 큰 사전의 경우이 솔루션은 여러 번 반복되므로 Python이 매핑을 반전 / 반전시키는 것보다 훨씬 효율적이지 않습니다 items()
.
-1
여전히 질문에 대답 하지 않기 때문에 내 의견입니다.
람다를 좋아한다면 위에서 제안한 다른 기능 외에도 :
invert = lambda mydict: {v:k for k, v in mydict.items()}
또는 다음과 같이 할 수도 있습니다.
invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
이 작업을 수행하는 가장 좋은 방법은 클래스를 정의하는 것입니다. 다음은 "대칭 사전"의 구현입니다.
class SymDict:
def __init__(self):
self.aToB = {}
self.bToA = {}
def assocAB(self, a, b):
# Stores and returns a tuple (a,b) of overwritten bindings
currB = None
if a in self.aToB: currB = self.bToA[a]
currA = None
if b in self.bToA: currA = self.aToB[b]
self.aToB[a] = b
self.bToA[b] = a
return (currA, currB)
def lookupA(self, a):
if a in self.aToB:
return self.aToB[a]
return None
def lookupB(self, b):
if b in self.bToA:
return self.bToA[b]
return None
삭제 및 반복 방법은 필요한 경우 쉽게 구현할 수 있습니다.
이 구현은 전체 사전을 뒤집는 것보다 훨씬 효율적입니다 (이 페이지에서 가장 인기있는 솔루션 인 것 같습니다). 말할 것도없이 SymDict에서 원하는만큼 값을 추가하거나 제거 할 수 있으며, 역 사전은 항상 유효합니다. 전체 사전을 한 번만 뒤집는 경우에는 해당되지 않습니다.
dictresize
접근법은 파이썬에게 그 가능성을 부인합니다.
고유하지 않은 값을 처리하고 고유 한 경우의 모양을 유지합니다.
inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}
파이썬 3.x를 들어, 교체 itervalues
와 함께 values
.
함수는 list 유형의 값에 대해 대칭입니다. reverse_dict (reverse_dict (dictionary))를 수행 할 때 튜플이 목록에 포함됩니다.
def reverse_dict(dictionary):
reverse_dict = {}
for key, value in dictionary.iteritems():
if not isinstance(value, (list, tuple)):
value = [value]
for val in value:
reverse_dict[val] = reverse_dict.get(val, [])
reverse_dict[val].append(key)
for key, value in reverse_dict.iteritems():
if len(value) == 1:
reverse_dict[key] = value[0]
return reverse_dict
사전은 값과 달리 사전 내에 하나의 고유 키를 필요로하기 때문에 새로운 특정 키에 포함되도록 정렬 된 값을 역순으로 추가해야합니다.
def r_maping(dictionary):
List_z=[]
Map= {}
for z, x in dictionary.iteritems(): #iterate through the keys and values
Map.setdefault(x,List_z).append(z) #Setdefault is the same as dict[key]=default."The method returns the key value available in the dictionary and if given key is not available then it will return provided default value. Afterward, we will append into the default list our new values for the specific key.
return Map
Bi-jective 맵을위한 빠른 기능 솔루션 (값이 고유하지 않음) :
from itertools import imap, groupby
def fst(s):
return s[0]
def snd(s):
return s[1]
def inverseDict(d):
"""
input d: a -> b
output : b -> set(a)
"""
return {
v : set(imap(fst, kv_iter))
for (v, kv_iter) in groupby(
sorted(d.iteritems(),
key=snd),
key=snd
)
}
이론적으로 이것은 명령형 솔루션 과 같이 세트에 하나씩 추가하거나 목록에 추가하는 것보다 빠릅니다 .
불행히도 값은 정렬 가능해야하며 정렬은 그룹별로 필요합니다.
n
원래 dict의 요소가 주어지면 O(n log n)
dict의 항목을 정렬해야하기 때문에 접근 방식에 시간이 복잡하고 순진한 접근 방식에는 O(n)
시간이 복잡합니다. 모두를 위해 나는 당신의 접근 방식이 더 빨리 터무니없이 큰까지있을 수 있습니다 알고 dict
에서의 연습 하지만, 그것은 확실히 이론에 있지 빠릅니다.
def invertDictionary(d):
myDict = {}
for i in d:
value = d.get(i)
myDict.setdefault(value,[]).append(i)
return myDict
print invertDictionary({'a':1, 'b':2, 'c':3 , 'd' : 1})
{1 : [ 'a', 'd'], 2 : [ 'b'], 3 : [ 'c']}와 같이 출력을 제공합니다.
dict.items
(또는 iteritems
Python 2에서) 키-값 쌍을 동시에 반복하는 것이 각 값을 개별적으로 추출하는 것보다 효율적입니다. 또한 다른 사람을 복제하는 답변에 설명을 추가하지 않았습니다.
def reverse_dictionary(input_dict):
out = {}
for v in input_dict.values():
for value in v:
if value not in out:
out[value.lower()] = []
for i in input_dict:
for j in out:
if j in map (lambda x : x.lower(),input_dict[i]):
out[j].append(i.lower())
out[j].sort()
return out
이 코드는 다음과 같습니다.
r = reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']})
print(r)
{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}
완전히 다른 것이 아니라 Cookbook의 약간 다시 작성된 요리법. setdefault
인스턴스를 통해 전달할 때마다 유지 방법을 사용하여 더욱 최적화되었습니다 .
def inverse(mapping):
'''
A function to inverse mapping, collecting keys with simillar values
in list. Careful to retain original type and to be fast.
>> d = dict(a=1, b=2, c=1, d=3, e=2, f=1, g=5, h=2)
>> inverse(d)
{1: ['f', 'c', 'a'], 2: ['h', 'b', 'e'], 3: ['d'], 5: ['g']}
'''
res = {}
setdef = res.setdefault
for key, value in mapping.items():
setdef(value, []).append(key)
return res if mapping.__class__==dict else mapping.__class__(res)
CPython 3.x에서 실행되도록 설계되었으며 2.x mapping.items()
는mapping.iteritems()
내 컴퓨터에서 다른 예제보다 약간 빠르게 실행됩니다.
dict
다음 끝에 올바른 유형의 클래스로 시작하지 않고 원하는 클래스로 변환하면 완전히 피할 수있는 성능 저하가 발생하는 것처럼 보입니다.
나는 사이클 'for'와 메소드 '.get ()'의 도움으로 이것을 작성했으며 'map'은 함수이기 때문에 사전의 이름 'map'을 'map1'로 변경했습니다.
def dict_invert(map1):
inv_map = {} # new dictionary
for key in map1.keys():
inv_map[map1.get(key)] = key
return inv_map
값이 고유하지 않고 해시 (1 차원) 일 수있는 경우 :
for k, v in myDict.items():
if len(v) > 1:
for item in v:
invDict[item] = invDict.get(item, [])
invDict[item].append(k)
else:
invDict[v] = invDict.get(v, [])
invDict[v].append(k)
그리고 한 차원 만 더 깊이 파고 들어야한다면 재귀를 사용하십시오.
def digList(lst):
temp = []
for item in lst:
if type(item) is list:
temp.append(digList(item))
else:
temp.append(item)
return set(temp)
for k, v in myDict.items():
if type(v) is list:
items = digList(v)
for item in items:
invDict[item] = invDict.get(item, [])
invDict[item].append(k)
else:
invDict[v] = invDict.get(v, [])
invDict[v].append(k)
{"foo": "bar"}
을 {'b': ['foo'], 'a': ['foo'], 'r': ['foo']}
하고 어떤 값이있는 경우 예외가 발생 myDict
하지 않은 반복 가능한 것입니다. 여기서 구현하려는 동작이 확실하지 않지만 실제로 구현 한 것은 아무도 원하지 않는 것입니다.
my_map.items()
으로 잘 작동