दो तरह से / रिवर्स नक्शा [डुप्लिकेट]


101

मैं अजगर में यह स्विचबोर्ड काम कर रहा हूं, जहां मुझे यह जानने की ज़रूरत है कि कौन किससे बात कर रहा है, इसलिए यदि ऐलिस -> बॉब, तो इसका मतलब है कि बॉब -> एलिस।

हां, मैं दो हैश मानचित्रों को आबाद कर सकता हूं, लेकिन मैं सोच रहा हूं कि क्या किसी को एक के साथ ऐसा करने का विचार है।

या किसी अन्य डेटा संरचना का सुझाव दें।

कोई एकाधिक वार्तालाप नहीं हैं। मान लीजिए कि यह एक ग्राहक सेवा कॉल सेंटर के लिए है, इसलिए जब ऐलिस स्विचबोर्ड में डायल करता है, तो वह केवल बॉब से बात करने वाला है। उसके जवाब भी उसके पास ही जाते हैं।


15
ध्यान दें कि आप एक विशेषण मानचित्र का वर्णन कर रहे हैं।
निक डंडौलकिस

यहां एक सरल जीवनी शब्दकोश कार्यान्वयन है , हालांकि मुझे नहीं पता कि यह आपके प्रदर्शन की आवश्यकताओं को पूरा करेगा या नहीं। ( पाइथन के लिए बढ़ावा देने वाले बिमप पर इस ब्लॉग लेख से लिंक , जिसमें विषय की कुछ अच्छी चर्चा है।)
प्रणाली PAUSE

2
अगर एलिस बॉब से बात कर रही है, तो मैं इसे लेती हूं कि वह चार्ल्स से बात नहीं कर सकती; ना ही बॉब किसी और से बात कर सकता है? साथ ही, किसी भी समय आप कितने लोगों और कितनी बातचीत कर सकते हैं?
सिस्टम PAUSE

नहीं ... मेरे स्विचबोर्ड पर नहीं। कोई भी संदेश जो एलिस मुझे भेजता है उसे बॉब जाना होगा। इसका सिर्फ मैं एक साथ बातचीत के हजारों मार्ग होगा। लेकिन प्रत्येक व्यक्ति एक समय में केवल एक ही व्यक्ति से बात करता है।
सुधीर जोनाथन

1
नहीं ... मुझे ग्राहक के संदेशों को ऑपरेटर के पास भेजने की आवश्यकता है और इसके विपरीत ... किसी भी तरह से बातचीत को संग्रहीत नहीं करना।
सुधीर जोनाथन

जवाबों:


90

आप अपने स्वयं के शब्दकोश प्रकार को उप-वर्ग बनाकर dictऔर अपने इच्छित तर्क को जोड़कर बना सकते हैं। यहाँ एक मूल उदाहरण दिया गया है:

class TwoWayDict(dict):
    def __setitem__(self, key, value):
        # Remove any previous connections with these values
        if key in self:
            del self[key]
        if value in self:
            del self[value]
        dict.__setitem__(self, key, value)
        dict.__setitem__(self, value, key)

    def __delitem__(self, key):
        dict.__delitem__(self, self[key])
        dict.__delitem__(self, key)

    def __len__(self):
        """Returns the number of connections"""
        return dict.__len__(self) // 2

और यह इस तरह काम करता है:

>>> d = TwoWayDict()
>>> d['foo'] = 'bar'
>>> d['foo']
'bar'
>>> d['bar']
'foo'
>>> len(d)
1
>>> del d['foo']
>>> d['bar']
Traceback (most recent call last):
  File "<stdin>", line 7, in <module>
KeyError: 'bar'

मुझे यकीन है कि मैंने सभी मामलों को कवर नहीं किया था, लेकिन आपको शुरू करना चाहिए।


2
@ सुधीरजोनथन: आप इस विचार के साथ बहुत आगे जा सकते हैं - उदाहरण के लिए, एक .addविधि जोड़ें ताकि आप d.add('Bob', 'Alice')मेरे द्वारा दिखाए गए वाक्यविन्यास का उपयोग करने के बजाय ऐसा कर सकें । मैं कुछ त्रुटि हैंडलिंग भी शामिल करूंगा। लेकिन आपको मूल विचार मिलता है। :)
साशा चेदिगोव ने

1
मुझे लगता है कि यह उन परिवर्धन के अंतर्गत आता है, लेकिन नए सेट करते समय पुरानी प्रमुख जोड़ियों को हटाना मददगार d['foo'] = 'baz'होगा ( इसके अलावा barकुंजी को हटाने की आवश्यकता होगी )।
दाढ़ी

@TobiasKienzler: आप सही हैं, लेकिन इसे प्रश्न में एक धारणा के रूप में सूचीबद्ध किया गया था।
साशा चोडगोव

5
इसके अलावा एक उल्लेख के लायक: उपवर्ग dictयहां कुछ भ्रामक व्यवहार पैदा करता है, क्योंकि यदि आप कुछ प्रारंभिक सामग्री के साथ वस्तु बनाते हैं, तो संरचना टूट जाएगी। __init__एक निर्माण d = TwoWayDict({'foo' : 'bar'})को ठीक से काम करने की अनुमति देने के लिए ओवरराइड करने की आवश्यकता है ।
हेनरी कीटर

19
बस यह उल्लेख करना चाहता हूं कि इसके लिए एक पुस्तकालय है pip install bidict:। URL: pypi.python.org/pypi/bidict
user1036719

45

अपने विशेष मामले में आप दोनों को एक शब्दकोश में संग्रहीत कर सकते हैं:

relation = {}
relation['Alice'] = 'Bob'
relation['Bob'] = 'Alice'

चूंकि आप जो वर्णन कर रहे हैं वह एक सममित संबंध है। A -> B => B -> A


3
हम्म ... हाँ, मुझे यह सबसे अच्छा लगता है। दो प्रविष्टियों को बनाने से बचने की कोशिश कर रहा था, लेकिन यह अब तक का सबसे अच्छा विचार है।
सुधीर जोनाथन

1
फिर भी लगता है कि एक दो तरह का नक्शा संभव होना चाहिए: - /
सुधीर जोनाथन

अगर यह कुशल होना है, तो कवर के तहत आपको कुछ इंडेक्स डेटा संरचना में अनुक्रमित होने के लिए दोनों की आवश्यकता है - चाहे वह हैश हो, सॉर्ट की गई सूची, बाइनरी ट्री, ट्राइ, सिस्टेस से भरा प्रत्यय सरणी, या कुछ भी अधिक विदेशी। पाइथन में ऐसा करने का सरल तरीका हैश का उपयोग करना है।
क्रैगन जेवियर सीटेकर

@SudhirJonathan यदि आप वास्तव में दो तरह से मानचित्र पसंद करते हैं, तो इस प्रश्न में वर्णित उदाहरण के अनुसार बोली पर एक नज़र डालें - अया द्वारा चर्चा किए गए प्रदर्शन मुद्दों पर ध्यान दें, हालांकि मेरे द्वैध प्रश्न पर टिप्पणी ।
टोबियास किंजलर

25

मुझे पता है कि यह एक पुराना सवाल है, लेकिन मैं इस समस्या के लिए एक और महान समाधान का उल्लेख करना चाहता था, अर्थात् अजगर पैकेज बोली । यह उपयोग करने के लिए बेहद सीधा है:

from bidict import bidict
map = bidict(Bob = "Alice")
print(map["Bob"])
print(map.inv["Alice"])

24

मैं बस एक दूसरे हैश, के साथ आबाद होगा

reverse_map = dict((reversed(item) for item in forward_map.items()))

7
वहाँ कुछ अतिरिक्त कोष्ठक मिला:reverse_map = dict(reversed(item) for item in forward_map.items())
एंड्री Drozdyuk

1
यदि आप आगे के बारे में जानकारी नहीं देते हैं तो अच्छा आसान तरीका है। मैं प्रयोग किया जाता हैmy_dict.update(dict(reversed(item) for item in my_dict.items()))
गिली

पायथन 3 में इस कोड का उपयोग करते समय मुझे एक चेतावनी मिलती है Unexpected type(s): (Generator[Iterator[Union[str, Any]], Any, None]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]]):। किसी भी विचार कैसे चेतावनी से छुटकारा पाने के लिए?
केर्विन स्नीजर्स

9

दो हैश मानचित्र वास्तव में संभवतः सबसे तेज़ प्रदर्शन करने वाला समाधान है जिससे आप स्मृति को छोड़ सकते हैं। मैं उन लोगों को एक ही वर्ग में लपेटता हूं - प्रोग्रामर पर बोझ यह सुनिश्चित करने में है कि दो हैश नक्शे सही तरीके से सिंक हो जाएं।


2
+1, यह मूल रूप से क्या बोली जाती है, mydict[:value]प्राप्त करने के लिए उलटा मानचित्रण तक पहुँचने के लिए चीनी का उपयोग key(कुछ प्रदर्शन की लागत पर)
टोबियास किंजलर

6

आपके दो अलग-अलग मुद्दे हैं।

  1. आपके पास "वार्तालाप" ऑब्जेक्ट है। यह दो व्यक्तियों को संदर्भित करता है। चूंकि एक व्यक्ति के कई वार्तालाप हो सकते हैं, आपके पास कई-से-कई संबंध हैं।

  2. आपके पास एक व्यक्ति से बातचीत की सूची के लिए एक मानचित्र है। रूपांतरण में व्यक्तियों की एक जोड़ी होगी।

कुछ ऐसा करो

from collections import defaultdict
switchboard= defaultdict( list )

x = Conversation( "Alice", "Bob" )
y = Conversation( "Alice", "Charlie" )

for c in ( x, y ):
    switchboard[c.p1].append( c )
    switchboard[c.p2].append( c )

5

नहीं, दो शब्दकोशों बनाए बिना ऐसा करने का कोई तरीका नहीं है। तुलनीय प्रदर्शन जारी रखने के लिए केवल एक शब्दकोश के साथ इसे लागू करना कैसे संभव होगा?

आप एक कस्टम प्रकार बनाने से बेहतर हैं जो दो शब्दकोशों को अलग करता है और आप जो कार्यक्षमता चाहते हैं उसे उजागर करते हैं।




2

एक अन्य संभावित समाधान उप-वर्ग को लागू करना है dict, जो मूल शब्दकोश रखता है और इसके उलट संस्करण का ट्रैक रखता है। यदि कुंजी और मान ओवरलैप हो रहे हों, तो दो अलग-अलग डाइक को रखना उपयोगी हो सकता है।

class TwoWayDict(dict):
    def __init__(self, my_dict):
        dict.__init__(self, my_dict)
        self.rev_dict = {v : k for k,v in my_dict.iteritems()}

    def __setitem__(self, key, value):
        dict.__setitem__(self, key, value)
        self.rev_dict.__setitem__(value, key)

    def pop(self, key):
        self.rev_dict.pop(self[key])
        dict.pop(self, key)

    # The above is just an idea other methods
    # should also be overridden. 

उदाहरण:

>>> d = {'a' : 1, 'b' : 2} # suppose we need to use d and its reversed version
>>> twd = TwoWayDict(d)    # create a two-way dict
>>> twd
{'a': 1, 'b': 2}
>>> twd.rev_dict
{1: 'a', 2: 'b'}
>>> twd['a']
1
>>> twd.rev_dict[2]
'b'
>>> twd['c'] = 3    # we add to twd and reversed version also changes
>>> twd
{'a': 1, 'c': 3, 'b': 2}
>>> twd.rev_dict
{1: 'a', 2: 'b', 3: 'c'}
>>> twd.pop('a')   # we pop elements from twd and reversed  version changes
>>> twd
{'c': 3, 'b': 2}
>>> twd.rev_dict
{2: 'b', 3: 'c'}

2

Pypi पर संग्रह-विस्तारित लाइब्रेरी है: https://pypi.python.org/pypi/collections-exta.com/0.0

आपत्ति वर्ग का उपयोग करना उतना ही आसान है:

RESPONSE_TYPES = bijection({
    0x03 : 'module_info',
    0x09 : 'network_status_response',
    0x10 : 'trust_center_device_update'
})
>>> RESPONSE_TYPES[0x03]
'module_info'
>>> RESPONSE_TYPES.inverse['network_status_response']
0x09

2

मुझे टिप्पणियों में से एक में बोली लगाने का सुझाव पसंद है।

pip install bidict

उपयोग:

# This normalization method should save hugely as aDaD ~ yXyX have the same form of smallest grammar.
# To get back to your grammar's alphabet use trans

def normalize_string(s, nv=None):
    if nv is None:
        nv = ord('a')
    trans = bidict()
    r = ''
    for c in s:
        if c not in trans.inverse:
            a = chr(nv)
            nv += 1
            trans[a] = c
        else:
            a = trans.inverse[c]
        r += a
    return r, trans


def translate_string(s, trans):
    res = ''
    for c in s:
        res += trans[c]
    return res


if __name__ == "__main__":
    s = "bnhnbiodfjos"

    n, tr = normalize_string(s)
    print(n)
    print(tr)
    print(translate_string(n, tr))    

चूंकि इसके बारे में बहुत डॉक्स नहीं हैं। लेकिन मुझे उन सभी विशेषताओं की आवश्यकता है जो मुझे सही तरीके से काम करने की आवश्यकता है।

प्रिंटों:

abcbadefghei
bidict({'a': 'b', 'b': 'n', 'c': 'h', 'd': 'i', 'e': 'o', 'f': 'd', 'g': 'f', 'h': 'j', 'i': 's'})
bnhnbiodfjos

1

Kjbuckets C एक्सटेंशन मॉड्यूल एक "ग्राफ़" डेटा संरचना प्रदान करता है जो मुझे विश्वास है कि आपको जो चाहिए वह आपको देता है।


क्षमा करें, मैंने इसका उल्लेख नहीं किया है, लेकिन इसके ऐप इंजन पर ... इसलिए कोई सी एक्सटेंशन नहीं है।
सुधीर जोनाथन

1

dictयदि आप उन अन्य लोगों में से किसी को भी पसंद नहीं करते हैं, तो एक और दो-तरफ़ा शब्दकोश कार्यान्वयन अजगर वर्ग को बढ़ाकर किया जाता है:

class DoubleD(dict):
    """ Access and delete dictionary elements by key or value. """ 

    def __getitem__(self, key):
        if key not in self:
            inv_dict = {v:k for k,v in self.items()}
            return inv_dict[key]
        return dict.__getitem__(self, key)

    def __delitem__(self, key):
        if key not in self:
            inv_dict = {v:k for k,v in self.items()}
            dict.__delitem__(self, inv_dict[key])
        else:
            dict.__delitem__(self, key)

निर्माण को छोड़कर एक सामान्य अजगर शब्दकोश के रूप में इसका उपयोग करें:

dd = DoubleD()
dd['foo'] = 'bar'

1

एक तरह से मैं इस तरह की चीज़ करना पसंद करता हूँ:

{my_dict[key]: key for key in my_dict.keys()}

1
StackOverflow में आपका स्वागत है! कृपया अपने उत्तर को संपादित करें और अपने कोड के लिए और अधिक विवरण जोड़ें, अधिमानतः यह भी वर्णन जोड़ना कि यह 14 अन्य उत्तरों से अलग क्यों है। सवाल दस साल से अधिक पुराना है , और पहले से ही एक स्वीकृत जवाब है और कई अच्छी तरह से समझाया, अच्छी तरह से उत्थान वाले भी हैं। आपके पोस्ट में अधिक विस्तार के बिना, यह तुलनात्मक रूप से कम गुणवत्ता का है और संभवतः नीचे या हटा दिया जाएगा। उस अतिरिक्त जानकारी को जोड़ने से आपके उत्तर के अस्तित्व को सही ठहराने में मदद मिलेगी।
दास_जीक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.