そのような辞書を考えると:
my_map = {'a': 1, 'b': 2}
このマップを反転して取得するにはどうすればよいですか:
inv_map = {1: 'a', 2: 'b'}
そのような辞書を考えると:
my_map = {'a': 1, 'b': 2}
このマップを反転して取得するにはどうすればよいですか:
inv_map = {1: 'a', 2: 'b'}
回答:
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((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()))
(ディクショナリビューのPythonドキュメントでは、これらの要素が同じ順序であることが明示的に保証され.keys()
て.values()
いるため、上記のアプローチが機能することに注意してください。)
または:
inv_map = dict((my_map[k], k) for k in my_map)
またはpython 3.0のdict内包表記を使用して
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
or などの他のマッピングタイプと交換できるという利点があります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
おり、2回使用して元の状態に戻すことはできません。このように対称ではありません。Python 2.6でテストされています。これが、結果のディクテーションを印刷するための使用例です。
set
よりもを使用する場合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]
(Python 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)
2番目のソリューション。反転には辞書内包アプローチを使用します。
# Use this code to invert dictionaries that have unique values
inverted_dict = {value: key for key, value in dict.items()}
3番目のソリューション。反転アプローチを元に戻す(2番目のソリューションに依存):
# 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()
複数回ループするため、回答のPythonのマッピングよりもはるかに効率が悪いことに注意してください。
-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の値は好きなだけ追加または削除できます。逆辞書は常に有効なままです。これは、単に辞書全体を1度反転するだけでは当てはまりません。
dictresize
はありませんが、このアプローチではPythonの可能性が否定されます。
これにより、一意でない値が処理され、一意のケースの外観の多くが保持されます。
inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}
Pythonの3.xの、交換してくださいitervalues
とvalues
。
リスト型の値の関数は対称です。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
辞書は値とは異なり、辞書内に1つの一意のキーを必要とするため、新しい特定のキーに含めるには、逆の値を並べ替えのリストに追加する必要があります。
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
)
}
理論的には、命令型ソリューションのように、セットに1つずつ追加する(またはリストに追加する)よりも高速です。
残念ながら、値はソート可能でなければなりません。ソートはgroupbyで必要です。
n
元のdictの要素を考えるとO(n log n)
、dictのアイテムをソートする必要があるため、アプローチはO(n)
時間的に複雑ですが、単純な命令型のアプローチは時間的に複雑です。すべての人にとって、あなたのアプローチは実際には途方もなく大きいdict
s まで速くなる可能性があることを知っていますが、理論的にはそれは決して速くありません。
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']}
完全に異なるものではなく、クックブックのレシピを少し書き直しただけです。setdefault
インスタンスを通過するたびにではなく、retaining メソッドによってさらに最適化されます。
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()
私のマシンでは、他の例よりも少し速く実行されます
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)
そして、再帰を使用して、1つだけの次元を掘り下げる必要がある場合:
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()
同様に動作