দ্বিপথ / বিপরীত মানচিত্র [সদৃশ]


103

আমি এই সুইচবোর্ডটি অজগরটিতে করছি যেখানে আমার সাথে কে কার সাথে কথা বলছে তা ট্র্যাক করে রাখা দরকার, সুতরাং যদি অ্যালিস -> বব, তবে তার থেকে বোঝা যায় যে বব -> এলিস।

হ্যাঁ, আমি দুটি হ্যাশ মানচিত্র পপুলেশন করতে পারি, তবে আমি ভাবছি যে কারও কাছে এটির সাথে কাজ করার কোনও ধারণা আছে কিনা।

অথবা অন্য একটি ডেটা স্ট্রাকচারের পরামর্শ দিন।

একাধিক কথোপকথন নেই। ধরা যাক এটি কোনও গ্রাহক পরিষেবা কল সেন্টারের জন্য, সুতরাং অ্যালিস যখন স্যুইচবোর্ডে ডায়াল করে তখন তিনি কেবল ববয়ের সাথে কথা বলতে যাচ্ছেন। তার উত্তরগুলিও কেবল তার কাছে যায়।


15
মনে রাখবেন যে আপনি একটি দ্বিপ্রদীপক মানচিত্র বর্ণনা করছেন।
নিক ডানডৌলাকিস

এখানে একটি সাধারণ বাইজিক্ট ডিকশনারি বাস্তবায়ন , যদিও এটি আপনার কার্য সম্পাদনের প্রয়োজনীয়তা পূরণ করবে কিনা আমি জানি না। ( পাইথনের জন্য বিম্যাপ বাড়ানোর বিষয়ে এই ব্লগ নিবন্ধের লিঙ্ক , যা বিষয়ে কিছুটা সুন্দর আলোচনা রয়েছে))
সিস্টেম পজ

4
অ্যালিস যদি ববয়ের সাথে কথা বলছেন, আমি এটি গ্রহণ করি যে সে চার্লসের সাথেও কথা বলতে পারে না; বা বব অন্য কারও সাথে কথা বলতে পারে? এছাড়াও, আপনি কোনও নির্দিষ্ট সময়ে কত লোক এবং কত কথোপকথন করতে পারেন?
সিস্টেম PAUSE

না ... আমার সুইচবোর্ডে নেই এলিস আমাকে যে বার্তা পাঠায় তা ববয়ের কাছে যেতে হবে। এটি ঠিক আমি হাজার হাজার যুগপত কথোপকথনকে ঘুরিয়ে দেব। তবে প্রতিটি ব্যক্তি একবারে অন্য একজনের সাথে কথা বলে।
সুধীর জনাথন

4
না ... আমাকে কেবল গ্রাহকের বার্তাগুলি অপারেটরের কাছে পৌঁছে দেওয়া প্রয়োজন এবং এর বিপরীতে ... এমনকি কোনওভাবে কথোপকথনও সংরক্ষণ করে রাখছি না।
সুধীর জনাথন

উত্তর:


93

সাবক্লাসিং 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'

আমি নিশ্চিত যে আমি সমস্ত মামলা কভার করি নি, তবে এটি আপনাকে শুরু করা উচিত।


4
@ সুধীরজানাথন: আপনি এই ধারণার সাথে আরও অনেকখানি এগিয়ে যেতে পারেন - উদাহরণস্বরূপ, একটি .addপদ্ধতি যুক্ত করুন যাতে আপনি d.add('Bob', 'Alice')আমার প্রদর্শিত সিনট্যাক্সটি ব্যবহার না করে যেমন কাজ করতে পারেন । আমি কিছু ত্রুটি পরিচালনা পরিচালনাও অন্তর্ভুক্ত করব। তবে আপনি প্রাথমিক ধারণা পেতে পারেন। :)
সাশা চেদিগোভ

4
আমার ধারণা এটি এই সংযোজনগুলির মধ্যে পড়ে তবে নতুন সেট করার সময় পুরানো কী জোড়া মুছে ফেলা সহায়ক d['foo'] = 'baz'হবে ( অতিরিক্তভাবে barকীটি সরিয়ে ফেলতে হবে )।
beardc

@ তোবিয়াস কিয়েঞ্জার: আপনি সঠিক, তবে এটি প্রশ্নের একটি অনুমান হিসাবে তালিকাভুক্ত হয়েছিল।
সাশা চেদিগোভ

5
উল্লেখ করার মতো বিষয়: সাবক্লাসিং dictএখানে কিছু বিভ্রান্তিমূলক আচরণ তৈরি করে, কারণ যদি আপনি কিছু প্রাথমিক সামগ্রী দিয়ে অবজেক্টটি তৈরি করেন তবে কাঠামোটি নষ্ট হয়ে যাবে। __init__কোনও নির্মাণকে d = TwoWayDict({'foo' : 'bar'})সঠিকভাবে কাজ করার অনুমতি দেওয়ার জন্য ওভাররাইড করা দরকার ।
হেনরি কিটার

19
শুধু এই জন্য একটি লাইব্রেরি আছে উল্লেখ করতে চাই: pip install bidict। ইউআরএল: pypi.python.org/pypi/bidict
ব্যবহারকারী 1036719

46

আপনার বিশেষ ক্ষেত্রে আপনি উভয়ই একটি অভিধানে সঞ্চয় করতে পারেন:

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

যেহেতু আপনি যা বর্ণনা করছেন তা একটি প্রতিসম সম্পর্ক। A -> B => B -> A


4
হুম ... হ্যাঁ, আমি এটিকে সবচেয়ে পছন্দ করি। দুটি এন্ট্রি না করা চেষ্টা করছিল, তবে এটি এখন পর্যন্ত সেরা ধারণা।
সুধীর জনাথন

4
তবুও ভাবেন দ্বিপথের মানচিত্রটি হওয়া উচিত: - /
সুধীর জোনাথন

যদি এটি দক্ষ হতে হয়, তবে কভারগুলির নীচে আপনার উভয় কীগুলির কিছু সূচি ডেটা কাঠামোতে সূচিকাগুলি তৈরি করতে হবে - তা হ্যাশ, সাজানো তালিকা, বাইনারি ট্রি, একটি ট্রাই, সিস্ট্রিংগুলিতে পূর্ণ প্রত্যয় অ্যারে বা এমন কিছুর কিছু হোক না কেন আরও বিদেশী পাইথনে এটি করার সহজ উপায় হ্যাশ ব্যবহার করা।
ক্রেজেন জাভিয়ার সিটেকার

@SudhirJonathan আপনি একটি সত্যিকারের দুটি উপায় মানচিত্র পছন্দ করেন, কটাক্ষপাত আছে bidict উল্লেখ উদাঃ যেমন এই প্রশ্নের নোট কর্মক্ষমতা সমস্যাগুলির আলোচনা - Aya মন্তব্যের আমার প্রতারিত প্রশ্ন যদিও।
টোবিয়াস কেইনজলার

25

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি এই সমস্যার আরও একটি দুর্দান্ত সমাধান উল্লেখ করতে চেয়েছিলাম, যাহা পাইথন প্যাকেজ বিডিক্ট । এটি ব্যবহারের জন্য অত্যন্ত সোজা এগিয়ে:

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

24

আমি কেবল একটি দ্বিতীয় হ্যাশ পপুলেশন করব with

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

7
সেখানে কিছু অতিরিক্ত বন্ধনী পেয়েছেন:reverse_map = dict(reversed(item) for item in forward_map.items())
অ্যান্ড্রি দ্রোজডিয়ুক

4
খুব সহজ উপায় যদি আপনি ডিকটি আরও আপডেট করবেন না। আমি ব্যবহার করেছি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]])। কোনও ধারণা কীভাবে সতর্কতা থেকে মুক্তি পাবেন?
কেরউইন স্নিজার্ডার

অজগর 3 এ, এটির সাথে কোনও সতর্কতা নেই:my_dict.update({item[1]: item[0] for item in my_dict.items()})
মিমিদিনহল

9

দুটি হ্যাশ মানচিত্র সম্ভবত দ্রুতগতি সম্পন্ন সমাধান যা আপনি স্মরণশক্তি ছাড়িয়ে নিতে পারবেন তা ধরে নেওয়া। আমি তাদের একক শ্রেণিতে আবদ্ধ করব - প্রোগ্রামারের উপর বোঝা হ'ল যে দুটি হ্যাশ মানচিত্র সঠিকভাবে সিঙ্ক আপ হয়েছে।


4
+1 টি, এর কি যে bidict মূলত করে, প্লাস ব্যবহার করে বিপরীত ম্যাপিং ব্যবহার করার জন্য চিনি mydict[:value]প্রাপ্ত key(কিছু কর্মক্ষমতা খরচে)
Tobias Kienzler

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

না, দুটি অভিধান তৈরি না করে এটি করার সত্যিই কোনও উপায় নেই। তুলনামূলক পারফরম্যান্সের অব্যাহত রাখার সময় কীভাবে এটি কেবলমাত্র একটি অভিধান দিয়ে এটি প্রয়োগ করা সম্ভব হবে?

আপনি এমন একটি কাস্টম প্রকার তৈরি করা ভাল যা দুটি অভিধান সজ্জিত করে এবং আপনার পছন্দসই কার্যকারিতাটি প্রকাশ করে।


3

একটি কম ভার্বোজ উপায়, এখনও বিপরীত ব্যবহার করে:

dict(map(reversed, my_dict.items()))


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

পাইপিতে সংগ্রহগুলি-বর্ধিত গ্রন্থাগার রয়েছে: https://pypi.python.org/pypi/col લેક્-- এক্সটেন্ডেড ০..6.০

বাইজেকশন ক্লাস ব্যবহার করা যেমনটি সহজ:

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

কেজবকেটস সি এক্সটেনশন মডিউল একটি "গ্রাফ" ডেটা স্ট্রাকচার সরবরাহ করে যা আমার বিশ্বাস আপনি যা চান তা আপনাকে দেয়।


দুঃখিত আমি এটি উল্লেখ করি নি, তবে এটি অ্যাপ ইঞ্জিনে ... সুতরাং কোনও সি এক্সটেনশান নেই।
সুধীর জনাথন

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

4
স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম! দয়া করে আপনার উত্তরটি সম্পাদনা করুন এবং আপনার কোডের জন্য আরও ব্যাখ্যা যুক্ত করুন, সম্ভবত 14 টি উত্তর থেকে পৃথক কেন তা বর্ণনা যুক্ত করুন। প্রশ্নটি দশ বছরেরও বেশি পুরানো , ইতিমধ্যে একটি স্বীকৃত উত্তর রয়েছে এবং অনেকগুলি ভালভাবে ব্যাখ্যা করা হয়েছে, ভাল-আপডভোটেড রয়েছে। আপনার পোস্টে আরও বিশদ ছাড়াই এটি তুলনামূলকভাবে নিম্ন মানের এবং সম্ভবত ডাউনভোটেড বা সরানো হবে। অতিরিক্ত তথ্য যুক্ত করা আপনার উত্তরের অস্তিত্ব ন্যায্যতা করতে সহায়তা করবে।
দাস_গীক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.