سؤال

لديه مشكلة مثيرة للاهتمام التي تبدو الأكثر Pythonic الحل.لنفترض أن لدي قائمة تعيينات {'id': id, 'url': url}.بعض ids في قائمة مكررة و أريد إنشاء قائمة جديدة ، مع كل إزالة التكرارات.لقد جاء مع الدالة التالية:

def unique_mapping(map):
    d = {}
    for res in map:
        d[res['id']] = res['url']

    return [{'id': id, 'url': d[id]} for id in d]

اعتقد انها فعالة جدا.ولكن هناك "أكثر Pythonic" الطريقة ؟ أو ربما أكثر كفاءة الطريقة ؟

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

المحلول

المثال الخاص بك يمكن إعادة كتابة قليلا لبناء أول قاموس باستخدام مولد التعبير وإزالة ضرورة بناء آخر تعيينات.فقط إعادة القديمة:

def unique_mapping(mappings):
    return dict((m['id'], m) for m in mappings).values()

على الرغم من أن هذا جاء بها باعتبارها واحدة بطانة, ما زلت أعتقد أنها جدا للقراءة.

هناك نوعان من الأشياء التي يجب أن نأخذ في الاعتبار عند استخدام الأصلي الخاص بك حل لي:

  • البنود لن يكون دائما عاد في نفس الترتيب كانوا في الأصل
  • بعد الدخول سوف الكتابة فوق الإدخالات السابقة مع نفس معرف

إذا كنت لا تمانع ، ثم أقترح الحل أعلاه.في حالة أخرى, هذه الوظيفة يحافظ على النظام يعامل الأولى واجه معرفات مع الأولوية:

def unique_mapping(mappings):
    addedIds = set()
    for m in mappings:
        mId = m['id']
        if mId not in addedIds:
            addedIds.add(mId)
            yield m

قد تحتاج إلى الاتصال مع list(unique_mappings(mappings)) إذا كنت في حاجة الى قائمة وليس مولد.

نصائح أخرى

وهناك زوجين من الأشياء التي يمكن أن تحسن.

  • انت أداء اثنين من الحلقات ، أحد أكثر الأصلي ديكت ، ثم مرة أخرى على نتيجة dict.هل يمكن بناء النتائج الخاصة بك في خطوة واحدة بدلا من ذلك.

  • يمكنك تغيير إلى استخدام المولدات ، لتجنب بناء قائمة كاملة مقدما.(استخدام قائمة(unique_mapping(البنود)) لتحويل قائمة كاملة إذا كنت في حاجة إليها)

  • هناك حاجة إلى تخزين قيمة عند فحص فقط عن التكرارات ، يمكنك استخدام مجموعة بدلا من ذلك.

  • كنت إعادة قاموس لكل عنصر بدلا من العودة الأصلي.هذه في الواقع قد تكون هناك حاجة (على سبيل المثال.أنت التعديل عليها و لا تريد أن تلمس الأصلي), ولكن إذا لم, لها أكثر كفاءة في استخدام القواميس التي تم إنشاؤها بالفعل.

وهنا التنفيذ:

def unique_mapping(items):
    s = set()
    for res in items:
        if res['id'] not in s:
            yield res
            s.add(res['id'])

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

>>> someListOfDicts= [
    {'url': 'http://a', 'id': 'a'}, 
    {'url': 'http://b', 'id': 'b'}, 
    {'url': 'http://c', 'id': 'a'}]

>>> dict( [(x['id'],x) for x in someListOfDicts ] ).values()

[{'url': 'http://c', 'id': 'a'}, {'url': 'http://b', 'id': 'b'}]
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top