जैसे एक शब्दकोश दिया:
my_map = {'a': 1, 'b': 2}
इस नक्शे को पाने के लिए कोई कैसे उल्टा कर सकता है:
inv_map = {1: 'a', 2: 'b'}
जैसे एक शब्दकोश दिया:
my_map = {'a': 1, 'b': 2}
इस नक्शे को पाने के लिए कोई कैसे उल्टा कर सकता है:
inv_map = {1: 'a', 2: 'b'}
जवाबों:
पायथन 2.7.x के लिए
inv_map = {v: k for k, v in my_map.iteritems()}
पायथन 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()))
(ध्यान दें कि शब्दकोश विचारों पर पायथन डॉक्स स्पष्ट रूप से गारंटी देता है .keys()
और .values()
उनके तत्व उसी क्रम में हैं, जो ऊपर दिए गए दृष्टिकोण को काम करने की अनुमति देता है।)
वैकल्पिक रूप से:
inv_map = dict((my_map[k], k) for k in my_map)
या अजगर के 3.0 की व्यापक समझ का उपयोग करना
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
यह रॉबर्ट द्वारा दिए गए उत्तर पर विस्तार करता है , जब आवेदन करने वाले के मान अद्वितीय नहीं होते हैं।
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.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]
(पायथन 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']}
पहला उपाय । Inverting के लिए कुंजी-मान अपने शब्दकोश एक प्रयोग में जोड़े 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())
)
विशेष रूप से एक बड़े हुक्म के लिए, ध्यान दें कि यह समाधान पायथन रिवर्स / मैपिंग को उल्टा करने की तुलना में बहुत कम कुशल है क्योंकि यह 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
।
प्रकार सूची के मूल्यों के लिए फ़ंक्शन सममित है; उलट-पुलट (रिवर्स_डिक्ट (डिक्शनरी)) करते समय ट्यूपल्स को सूचियों में शामिल किया जाता है
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
)
}
सिद्धांत रूप में यह सेट में जोड़ने (या सूची में जोड़कर) की तुलना में तेज होना चाहिए, एक-एक करके अनिवार्य समाधान में ।
दुर्भाग्य से मूल्यों को क्रमबद्ध करना पड़ता है, समूहन द्वारा छंटाई की आवश्यकता होती है।
n
मूल तानाशाही में तत्वों को देखते हुए , आपके दृष्टिकोण में O(n log n)
तानाशाह की वस्तुओं को छांटने की आवश्यकता के कारण समय की जटिलता होती है, जबकि अनुभवहीन अनिवार्य दृष्टिकोण में O(n)
समय की जटिलता होती है। सभी के लिए मैं अपने दृष्टिकोण तेजी से जब तक बड़ी मूर्खता हो सकता है पता है dict
में अभ्यास है, लेकिन यह निश्चित रूप से सिद्धांत रूप में नहीं तेज है।
मैं इसे अजगर 2 में इस तरह से करूंगा।
inv_map = {my_map[x] : x for x in my_map}
dict.items
(या iteritems
पायथन 2 में) अलग-अलग करना, कुंजियों की पुनरावृति करते समय प्रत्येक मूल्य को अलग-अलग निकालने से अधिक कुशल है।
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
पायथन 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
प्रत्येक समय के बजाय इसे प्राप्त करने की विधि द्वारा इसे बनाए रखने के द्वारा अनुकूलित किया गया है , यह futhermore है :
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)
सीपीएक्स 3.x के तहत चलाने के लिए डिज़ाइन किया गया, 2.x के mapping.items()
साथ बदलेंmapping.iteritems()
मेरी मशीन पर अन्य उदाहरणों की तुलना में थोड़ा तेज चलता है
dict
और फिर अंत में वांछित वर्ग में परिवर्तित करना (सही प्रकार की कक्षा के साथ शुरू करने के बजाय) मुझे ऐसा लग रहा है जैसे यह पूरी तरह से परिहार्य प्रदर्शन हिट है।
मैंने इसे 'for' और Method '.get ()' की मदद से लिखा था और मैंने डिक्शनरी के 'मैप' का नाम बदलकर 'मैप 1' कर दिया क्योंकि 'मैप' एक फंक्शन है।
def dict_invert(map1):
inv_map = {} # new dictionary
for key in map1.keys():
inv_map[map1.get(key)] = key
return inv_map
यदि मूल्य अद्वितीय नहीं हैं और एक हैश (एक आयाम) हो सकता है:
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()
के रूप में अच्छी तरह से काम करता है