سؤال

لا تسمح لغة بايثون باستخدام القواميس كمفاتيح في قواميس أخرى.هل هناك حل بديل لاستخدام القواميس غير المتداخلة كمفاتيح؟

كانت المشكلة العامة مع الكائنات غير القابلة للتجزئة الأكثر تعقيدًا وحالة الاستخدام المحددة الخاصة بي هي انتقلت الى هنا.كان الوصف الأصلي لحالة الاستخدام الخاصة بي غير صحيح.

هل كانت مفيدة؟

المحلول

إذا كان لديك قاموسًا غير قابل للتغيير حقًا (على الرغم من أنه ليس من الواضح بالنسبة لي سبب عدم استخدام قائمة الأزواج فقط:على سبيل المثال [('content-type', 'text/plain'), ('host', 'example.com')]) ، فيمكنك تحويل ملفك dict داخل:

  1. مجموعة من الأزواج.لقد فعلت ذلك بالفعل في سؤالك.أ tuple مطلوب بدلا من list لأن النتائج تعتمد على ترتيب العناصر وثباتها.

    >>> tuple(sorted(a.items()))
    
  2. مجموعة مجمدة.وهو نهج أكثر ملاءمة من الناحية الرياضية، كما يتطلب الأمر علاقة المساواة فقط على عناصر غير قابلة للتغيير dict, بينما يتطلب النهج الأول العلاقة الترتيبية إلى جانب المساواة.

    >>> frozenset(a.items())
    

نصائح أخرى

إذا كنت بحاجة إلى استخدام القواميس كمفاتيح، وأود أن تتسطح القاموس في الصفوف (tuple) من المجموعات.

وقد تجد هذا السؤال SO المفيد: <لأ href = "https://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-dictionaries-in-python" > ما هو أفضل وسيلة لتنفيذ القواميس المتداخلة؟

وهنا مثال على وحدة تسطيح التي من شأنها أن تتسطح القواميس: <لأ href = "http://yawpycrypto.sourceforge.net/html/public/Flatten.Flatten-module.html" يختلط = "نوفولو noreferrer" > http://yawpycrypto.sourceforge.net/html/public/Flatten.Flatten-module.html

وأنا لا أفهم تماما حالة استخدامك وأظن أن تحاول قبل الأوان تحسين شيء لا تحتاج الأمثل.

إحدى الطرق للقيام بذلك هي تصنيف الإملاء في فئة فرعية وتوفير طريقة التجزئة.أي:

class HashableDict(dict):
    def __hash__(self):
        return hash(tuple(sorted(self.iteritems())))

>>> d = HashableDict(a=1, b=2)
>>> d2 = { d : "foo"}
>>> d2[HashableDict(a=1, b=2)]
"foo"

ومع ذلك، ضع في اعتبارك الأسباب التي تجعل الإملاءات (أو أي أنواع قابلة للتغيير) لا تفعل ذلك:سيؤدي تغيير الكائن بعد إضافته إلى جدول التجزئة إلى تغيير التجزئة، مما يعني أن الإملاء سيضعه الآن في المجموعة الخطأ، وبالتالي سيتم إرجاع نتائج غير صحيحة.

إذا سلكت هذا الطريق، فإما أن تكون جداً تأكد من أن الإملاءات لن تتغير أبدًا بعد وضعها في القاموس الآخر، أو منعها بشكل فعال (على سبيل المثال.تأكد من أن التجزئة لا تتغير أبدًا بعد الاتصال الأول بـ __hash__, ، ورمي استثناء إذا لم يكن كذلك.)

وهم، وليس حالة استخدامك فقط memoizing المكالمات وظيفة؟ باستخدام الديكور، سيكون لديك دعم من السهل على وظائف التعسفية. ونعم، فإنهم غالبا ما مخلل الحجج، واستخدام المنطق الدائري، وهذا يعمل لأنواع غير القياسية طالما أنها يمكن مخلل.

وانظر على سبيل المثال هذا التحفيظ نموذجا

لتحويل someDictionary إلى مفتاح، قيام بذلك

key = tuple(sorted(someDictionary .items())

ويمكنك بسهولة عكس هذا مع dict( key )

وأنا لا أرى لماذا كنت تريد من أي وقت مضى للقيام بذلك، ولكن إذا كنت حقا حقا بحاجة إلى ذلك، قد تتمكن من محاولة التخليل القاموس:

mydict = {"a":1, "b":{"c":10}}
import pickle
key = pickle.dumps(mydict)

d[key] = value

وهذه وظيفة سيتم تحويل القاموس متداخلة إلى الصفوف (tuple) ثابتة من المجموعات التي يمكنك استخدامها كمفتاح:

def convert_dictionary_tuple(input_dict):
    """
    this function receives a nested dictionary and convert it to an immutable tuple of tuples with all the given
    dictionary data
    :param input_dict: a nested dictionary
    :return: immutable tuple of tuples with all the given dictionary data
    """
    tuples_dict = {}
    for key, value in input_dict.iteritems():
        if isinstance(value, dict):
            tuples_dict[key] = convert_dictionary_tuple(value)
        elif isinstance(value, list):
            tuples_dict[key] = tuple([convert_dictionary_tuple(v) if isinstance(v, dict) else v for v in value])
        else:
            tuples_dict[key] = value

    return tuple(sorted(tuples_dict.items()))

وأنا لا أعرف ما إذا كنت أفهم سؤالك بشكل صحيح، ولكنني سوف إعطائها

    d[repr(a)]=value

ويمكنك interate على القاموس مثل هذا

for el1 in d:
        for el2 in eval(el1):
                print el2,eval(el1)[el2]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top