قم بإزالة واستخراج العناصر المكررة من قائمة (مصفوفة) في Python

اعمال

يصف هذا القسم كيفية إنشاء قائمة جديدة في بايثون عن طريق إزالة أو استخراج العناصر المكررة من قائمة (مصفوفة).

التفاصيل التالية موصوفة هنا.

  • إزالة العناصر المكررة وإنشاء قوائم جديدة
    • لا تحتفظ بترتيب القائمة الأصلية:set()
    • يحافظ على ترتيب القائمة الأصلية:dict.fromkeys()وsorted()
    • مصفوفة ثنائية الأبعاد (قائمة القوائم)
  • استخراج العناصر المكررة وإنشاء قائمة جديدة
    • لا تحتفظ بترتيب القائمة الأصلية
    • يحافظ على ترتيب القائمة الأصلية
    • مصفوفة ثنائية الأبعاد (قائمة القوائم)

يمكن تطبيق نفس المفهوم على المجموعات بدلاً من القوائم.

انظر المقال التالي ل

  • إذا كنت تريد تحديد ما إذا كانت القائمة أو المجموعة بها عناصر مكررة
  • إذا كنت ترغب في استخراج العناصر المشتركة أو غير الشائعة بين القوائم المتعددة بدلاً من القائمة الواحدة

لاحظ أن القوائم يمكن أن تخزن أنواعًا مختلفة من البيانات وتختلف تمامًا عن المصفوفات. إذا كنت تريد التعامل مع المصفوفات في العمليات التي تتطلب حجم الذاكرة وعناوين الذاكرة أو المعالجة الرقمية للبيانات الكبيرة ، فاستخدم مصفوفة (مكتبة قياسية) أو NumPy.

إزالة العناصر المكررة وإنشاء قوائم جديدة

لا تحتفظ بترتيب القائمة الأصلية:set()

إذا لم تكن هناك حاجة للاحتفاظ بترتيب القائمة الأصلية ، فاستخدم set () ، التي تنشئ مجموعة أنواع محددة.

نوع المجموعة هو نوع بيانات لا يحتوي على عناصر مكررة. عند تمرير قائمة أو نوع بيانات آخر إلى set () ، يتم تجاهل القيم المكررة ويتم إرجاع كائن من مجموعة النوع حيث تكون القيم الفريدة فقط هي العناصر.

إذا كنت تريد أن تجعلها tuple ، فاستخدم tuple ().

l = [3, 3, 2, 1, 5, 1, 4, 2, 3]

print(set(l))
# {1, 2, 3, 4, 5}

print(list(set(l)))
# [1, 2, 3, 4, 5]

بالطبع ، يمكن أيضًا تركها كمجموعة. راجع المقالة التالية للحصول على مزيد من المعلومات حول مجموعة النوع المحدد.

يحافظ على ترتيب القائمة الأصلية:dict.fromkeys()وsorted()

إذا كنت تريد الحفاظ على ترتيب القائمة الأصلية ، فاستخدم طريقة class fromkeys () لنوع القاموس أو الوظيفة المضمنة التي تم فرزها ().

ينشئict.fromkeys () كائنًا جديدًا في القاموس تكون مفاتيحه عبارة عن قوائم ، أو مجموعات ، أو ما إلى ذلك ، محددة في الوسيطات. إذا تم حذف الوسيطة الثانية ، تكون القيمة بلا.

نظرًا لأن مفاتيح القاموس لا تحتوي على عناصر مكررة ، يتم تجاهل القيم المكررة كما في set (). بالإضافة إلى ذلك ، يمكن تمرير كائن القاموس كوسيطة إلى list () للحصول على قائمة عناصرها مفاتيح القاموس.

print(dict.fromkeys(l))
# {3: None, 2: None, 1: None, 5: None, 4: None}

print(list(dict.fromkeys(l)))
# [3, 2, 1, 5, 4]

لقد كان مضمونًا منذ Python 3.7 (CPython هو 3.6) أنict.fromkeys () يحافظ على ترتيب تسلسل الوسيطة. تستخدم الإصدارات السابقة الوظيفة المضمنة التي تم فرزها () على النحو التالي.

حدد فهرس أسلوب قائمة الصفوف () لمفتاح الوسيطة الخاص بالفرز ، والذي يقوم بإرجاع قائمة مرتبة بالعناصر.

index () هو طريقة تُرجع فهرس القيمة (رقم العنصر في القائمة) ، والذي يمكن تحديده كمفتاح Sorted () لفرز القائمة بناءً على ترتيب القائمة الأصلية. يتم تحديد مفتاح الوسيطة ككائن قابل للاستدعاء (قابل للاستدعاء) ، لذلك لا تكتب ().

print(sorted(set(l), key=l.index))
# [3, 2, 1, 5, 4]

مصفوفة ثنائية الأبعاد (قائمة القوائم)

بالنسبة للمصفوفات ثنائية الأبعاد (قوائم القوائم) ، ينتج عن الطريقة التي تستخدم set () أوict.fromkeys () خطأ TypeError.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]

# l_2d_unique = list(set(l_2d))
# TypeError: unhashable type: 'list'

# l_2d_unique_order = dict.fromkeys(l_2d)
# TypeError: unhashable type: 'list'

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

تحديد الوظائف التالية يتم الاحتفاظ بترتيب القائمة الأصلية ويعمل للقوائم ذات البعد الواحد والمجموعات.

def get_unique_list(seq):
    seen = []
    return [x for x in seq if x not in seen and not seen.append(x)]

print(get_unique_list(l_2d))
# [[1, 1], [0, 1], [0, 0], [1, 0]]

print(get_unique_list(l))
# [3, 2, 1, 5, 4]

تم استخدام تدوين استيعاب القائمة.

هنا ، نستخدم ما يلي

  • إذا كانت X في “X و Y” خاطئة في تقييم ماس كهربائى للمشغل ، فلن يتم تقييم Y (لم يتم تنفيذه).
  • طريقة append () ترجع بلا.

إذا لم تكن عناصر تسلسل القائمة الأصلية موجودة في المشاهدة ، فيتم تقييمها بعد ذلك.
يتم تنفيذ see.append (x) ويتم إضافة العنصر إلى المشاهدة.
لأن طريقة append () ترجع بلا و None هي False ، يقيّم not see.append (x) إلى True.
يصبح التعبير الشرطي في قائمة الفهم صحيحًا ويتم إضافته كعنصر من القائمة النهائية التي تم إنشاؤها.

إذا كانت عناصر القائمة الأصلية seq موجودة في الرؤية ، فإن x not in see هي False ، والتعبير الشرطي لتعبير list comprehension هو False.
لذلك ، لا يتم إضافتها كعناصر من القائمة النهائية التي تم إنشاؤها.

هناك طريقة أخرى تتمثل في تعيين محور الوسيطة في وظيفة np.unique () في NumPy ، على الرغم من أنه سيتم فرز النتيجة.

استخراج العناصر المكررة وإنشاء قائمة جديدة

لا تحتفظ بترتيب القائمة الأصلية

لاستخراج العناصر المكررة فقط من القائمة الأصلية ، استخدم collection.Counter ().
تُرجع المجموعات. العداد (فئة فرعية من القاموس) مع العناصر كمفاتيح وعدد العناصر كقيم.

import collections

l = [3, 3, 2, 1, 5, 1, 4, 2, 3]

print(collections.Counter(l))
# Counter({3: 3, 2: 2, 1: 2, 5: 1, 4: 1})

نظرًا لأنها فئة فرعية من القاموس ، يمكن استخدام العناصر () لاسترداد المفاتيح والقيم. يكفي استخراج مفاتيح رقمها اثنان أو أكثر.

print([k for k, v in collections.Counter(l).items() if v > 1])
# [3, 2, 1]

يحافظ على ترتيب القائمة الأصلية

كما هو موضح في المثال أعلاه ، منذ Python 3.7 ، فإن مفاتيح المجموعات تحتفظ Counter بترتيب القائمة الأصلية وما إلى ذلك.

في الإصدارات السابقة ، يكون الفرز باستخدام Sorted () كافيًا ، كما هو الحال مع حذف العناصر المكررة.

print(sorted([k for k, v in collections.Counter(l).items() if v > 1], key=l.index))
# [3, 2, 1]

إذا كنت ترغب في استخراج التكرارات كما هي ، فما عليك سوى ترك العناصر من القائمة الأصلية برقم اثنين أو أكثر. يتم الاحتفاظ بالترتيب أيضًا.

cc = collections.Counter(l)
print([x for x in l if cc[x] > 1])
# [3, 3, 2, 1, 1, 2, 3]

مصفوفة ثنائية الأبعاد (قائمة القوائم)

بالنسبة للمصفوفات ثنائية الأبعاد (قوائم القوائم) ، تكون الوظائف التالية ممكنة عندما لا يتم الاحتفاظ بترتيب القائمة الأصلية وعندما يتم الاحتفاظ بها ، على التوالي. وهي تعمل أيضًا مع القوائم ذات البعد الواحد والمجموعات.

l_2d = [[1, 1], [0, 1], [0, 1], [0, 0], [1, 0], [1, 1], [1, 1]]
def get_duplicate_list(seq):
    seen = []
    return [x for x in seq if not seen.append(x) and seen.count(x) == 2]

def get_duplicate_list_order(seq):
    seen = []
    return [x for x in seq if seq.count(x) > 1 and not seen.append(x) and seen.count(x) == 1]

print(get_duplicate_list(l_2d))
# [[0, 1], [1, 1]]

print(get_duplicate_list_order(l_2d))
# [[1, 1], [0, 1]]

print(get_duplicate_list(l))
# [3, 1, 2]

print(get_duplicate_list_order(l))
# [3, 2, 1]

إذا كنت تريد الاستخراج باستخدام التكرارات ، فاترك العناصر من القائمة الأصلية بعدد اثنين أو أكثر.

print([x for x in l_2d if l_2d.count(x) > 1])
# [[1, 1], [0, 1], [0, 1], [1, 1], [1, 1]]

لاحظ أنه نظرًا لأن التعقيد الحسابي للعدد () هو O (n) ، فإن الوظيفة الموضحة أعلاه والتي تنفذ العد () بشكل متكرر غير فعالة للغاية. قد تكون هناك طريقة أكثر ذكاءً.

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

# print(collections.Counter(l_2d))
# TypeError: unhashable type: 'list'