source

사전 매핑 반전/반전

lovecheck 2022. 11. 8. 21:12
반응형

사전 매핑 반전/반전

다음과 같은 사전이 제공됩니다.

my_map = {'a': 1, 'b': 2}

이 맵을 반전하여 다음 정보를 얻으려면 어떻게 해야 합니까?

inv_map = {1: 'a', 2: 'b'}

Python 3+:

inv_map = {v: k for k, v in my_map.items()}

Python 2:

inv_map = {v: k for k, v in my_map.iteritems()}

dict 내의 값이 고유하다고 가정하면 다음과 같습니다.

Python 3:

dict((v, k) for k, v in my_map.items())

Python 2:

dict((v, k) for k, v in my_map.iteritems())

my_map고유한 것은 아닙니다.

Python 3:

inv_map = {}
for k, v in my_map.items():
    inv_map[v] = inv_map.get(v, []) + [k]

Python 2:

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, []) + [k]

하면서 이를 매핑 을 ""로 함)dict ★★★dict★★★★★★★★★★★★★★★★)

def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))

이것을 시험해 보세요.

inv_map = dict(zip(my_map.values(), my_map.keys()))

(사전 뷰의 Python 문서는 다음을 명시적으로 보증합니다..keys() ★★★★★★★★★★★★★★★★★」.values()위의 접근방식을 사용할 수 있도록 요소를 동일한 순서로 설정합니다.)

대체 방법:

inv_map = dict((my_map[k], k) for k in my_map)

또는 python 3.0의 dict compreption을 사용합니다.

inv_map = {my_map[k] : k for k in my_map}

또 다른 기능적인 방법:

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))

키 도 있습니다.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().

이것은 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 훨씬list있는 가 매겨진 할 수 이러한 어플리케이션에는setdefault(v, []).append(k)하다, 사용하다setdefault(v, set()).add(k).

목록과 사전 이해의 조합.중복된 키를 처리할 수 있습니다.

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}

사전 값이 집합인 경우.예를 들어 다음과 같습니다.

some_dict = {"1":{"a","b","c"},
        "2":{"d","e","f"},
        "3":{"g","h","i"}}

그 반대는 다음과 같습니다.

some_dict = {vi: k  for k, v in some_dict.items() for vi in v}

출력은 다음과 같습니다.

{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}

예를 들어, 다음과 같은 사전이 있습니다.

dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}

그리고 당신은 그것을 거꾸로 하고 싶어합니다:

inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}

번째 솔루션사전에서 키-값 쌍을 반전하려면for -루프접근법:

# 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]}

독특한 가치를 가진 사전을 말하는 경우를 대비해서 답변은 많았지만 깨끗한 것을 찾지 못했습니다.

해결책은 다음과 같습니다.

from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)

예:

번째 dict가 "dict"인 경우my_map = {'c': 1, 'd': 5, 'a': 5, 'b': 10}

위의 코드를 실행하면 다음과 같은 결과가 나타납니다.

{5: ['a', 'd'], 1: ['c'], 10: ['b']}

위에 제시된 다른 기능 외에 람다를 좋아하는 경우:

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에서 원하는 만큼 값을 추가하거나 제거할 수 있습니다. 그러면 역사전이 항상 유효합니다. 사전 전체를 한 번 뒤집기만 하면 그렇지 않습니다.

가치관이 독특하지 않고, 조금 하드코어인 경우:

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

특히 큰 dict의 경우, 이 솔루션은 Python이 매핑을 리버스/인버트로 전환하는 보다 훨씬 덜 효율적이라는 점에 유의하십시오.items()러러번 。

그러면 고유하지 않은 값이 처리되고 고유한 케이스의 외관이 대부분 유지됩니다.

inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}

3. Python 3.x를 합니다.itervaluesvalues.

이 버전은 10000키 사전의 허용 버전보다 10% 이상 빠릅니다.

d = {i: str(i) for i in range(10000)}

new_d = dict(zip(d.values(), d.keys()))

이 질문에는 이미 좋은 답변이 많이 있다는 것을 알고 있습니다만, 중복되는 가치도 다루는 매우 깔끔한 솔루션을 소개하고 싶습니다.

def dict_reverser(d):
    seen = set()
    return {v: k for k, v in d.items() if v not in seen or seen.add(v)}

은 '아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.set.add 반환하다NonePython 서 python 。

여기 그것을 하는 다른 방법이 있다.

my_map = {'a': 1, 'b': 2}

inv_map= {}
for key in my_map.keys() :
    val = my_map[key]
    inv_map[val] = key
dict([(value, key) for key, value in d.items()])

함수는 유형 목록 값에 대해 대칭입니다. reverse_dict(reverse_dict(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

비주사적 맵을 위한 고속 기능 솔루션(값이 고유하지 않음):

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

이론적으로 이것은 필수 솔루션에서처럼 세트에 하나씩 추가하는(또는 목록에 추가하는) 것보다 빨라야 합니다.

유감스럽게도 값은 정렬 가능해야 하며 그룹별로 정렬해야 합니다.

python 2.7/3에 대해서 시험해 보세요.x

inv_map={};
for i in my_map:
    inv_map[my_map[i]]=i    
print inv_map
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']} 입니다.

현재 python 3.x 버전용 람다 솔루션:

d1 = dict(alice='apples', bob='bananas')
d2 = dict(map(lambda key: (d1[key], key), d1.keys()))
print(d2)

결과:

{'apples': 'alice', 'bananas': 'bob'}

이 솔루션에서는 중복은 체크되지 않습니다.

비고:

  • 람다 구문은 외부 스코프에서 d1에 액세스할 수 있으므로 현재 키만 전달합니다.태플을 반환합니다.
  • dict() 컨스트럭터는 튜플 목록을 받아들입니다.지도의 결과도 받아들이기 때문에 목록으로의 변환은 생략할 수 있습니다.
  • 이 솔루션에는 명시적인 내용이 없습니다.for루프를 사용하지 않습니다.list comprehension수학에 서투른 분들을 위해;-)

my_map의 값이 고유하지 않은 경우:에 따라서는 값이 고유하지 않을 뿐만 아니라 목록 내의 각 항목이 문자열 값, 숫자 및 다른 숫자의 세 가지 요소로 구성된 목록이라는 문제가 있었습니다.

예:

mymap['key1']다음과 같은 기능을 제공합니다.

[('xyz', 1, 2),
 ('abc', 5, 4)]

두 숫자 요소를 같은 위치에 두고 문자열 값만 키로 전환하려고 했습니다.루프를 위해 다른 네스트만 있으면 됩니다.

inv_map = {}
for k, v in my_map.items():
    for x in v:
        # with x[1:3] same as x[1], x[2]:
        inv_map[x[0]] = inv_map.get(x[0], []) + [k, x[1:3]]

예:

inv_map['abc']다음과 같은 이점이 있습니다.

[('key1', 1, 2),
 ('key1', 5, 4)]

이는 원래 사전에 고유하지 않은 값이 있는 경우에도 작동합니다.

def dict_invert(d):
    '''
    d: dict
    Returns an inverted dictionary 
    '''
    # Your code here
    inv_d = {}
    for k, v in d.items():
        if v not in inv_d.keys():
            inv_d[v] = [k]
        else:
            inv_d[v].append(k)
        inv_d[v].sort()
        print(f"{inv_d[v]} are the values")
        
    return inv_d

python 2에서는 그렇게 할 거예요.

inv_map = {my_map[x] : x for x in my_map}

완전히 다른 건 아니고 쿡북의 레시피를 조금 고쳐 쓴 것뿐이에요.유지보수에 의해 더욱 최적화됩니다.setdefaultinstance를 통과할 때마다 method를 지정합니다.

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)

2.x 치환용 CPython 3.x에서 동작하도록 설계되어 있습니다.mapping.items()와 함께mapping.iteritems()

여기의 다른 예에 비해, 내 머신은 조금 더 빨리 동작합니다.

언급URL : https://stackoverflow.com/questions/483666/reverse-invert-a-dictionary-mapping

반응형