7  المجموعة

بعد أن رأينا التلسلسل الذي هو نوع مجموعة مرتبة. ننتقل في درسنا هذا للبحث في نوعين آخرين يندرجان تحت الجمع المرقوم (وسيأتي بيان معنى الرقم):

المجموعة: set ويعبر عنها بالقوسين المتعرجين { }.

مثل الألوان: {الأحمر ,الأصفر ,الأخضر} إذ ليس بينها ترتيب معين

وباعتبار ما يُمكن شراؤه: {اللبن، الخبز، البيض}. أما باعتبار ما لديك في السلَّة قد تكون قائمة مثل [لبن, خبز, خبز, خبز, بيض] لأنك وضعت بعضها قبل بعض، ولأن فيها تكرارًا؛ فصار لدينا ترتيب (لاحظ أننا استعملنا القوسين المربعين هنا للدلالة على القائمة المرتبة)، والمجموعة لا ترتيب لها.

القاموس: dict وهي بالقوسين المتعرجين لكن عناصرها روابط { key: value }.

ومثالها أسعارُ سلة المشتريات على النحو التالي: {اللبن: 8, الخبز: 6, البيض: 15}.

المجموعة

المجموعة (set) هي جمع متغير يحوي أشياء مرقومة فريدة بلا ترتيب.

  • متغيرة: يعني أنها تقبل الإضافة والحذف والتعديل على عناصرها
  • فريدة: يعني أن العنصر لا يتكرر فيها
  • مرقومة: يعني أن عناصرها يجب أن تكون قابلة للرقم (hash)
  • بلا ترتيب: يعني أن العنصر ليس له موقع محدد فيها فليس له ما قبله وليس له ما بعده

انظر MutableSet في خريطة المجموعات: شكل 1.

تنشأ المجموعة الفريدة بالإجراء المنشئ set(). أو بالقوسين المتعرجين { }:

s1 = set([10, 20, 30])
s2 = {10, 20, 30}
assert s1 == s2

تقبل المجموعة لكونها جمعًا (Collection) العمليات التالية:

  • العد: len(s)
  • التكرار: for x in s
  • العضوية: x not in s

وباعتبارها مجموعة متغيرة (MutableSet)، فإنها تقبل الإجراءات التالية:

  • الإضافة: add
  • الحذف: discard
  • نزع عنصر عشوائي: pop
  • المحو: clear

ذكرنا أن شرط عضوية العنصر في المجموعة (set) وفي القاموس (dict) أن يكون مرقومًا؛ أي: قابلًا للرقم، أي: أن يُرمَزَ إليه برَقَم. ومعلومٌ أن الحروف أصلها أرقام: فكلمة cat مكونة من ثلاثة أرقام هي: 99, 97, 116.

ونبسِّط عمليَّة الرَّقم بمثال فنقول: إن إحدى طرق رَقْمِ الكلمة أن تجمع أرقام حروفها وتقسم على عدد ثابت ثم تأخذ باقي القسمة. فتقول: (99+97+116) % 100 = 12. (ملاحظة: علامة % هي لباقي القسمة) ويكون هذا الرقم (12) هو رمز الكلمة cat، ثم يستخدم هذا الرقم في الدلالة على موضع تخزين العنصر في الذاكرة. ولن نخوض في تفاصيل ذلك لأنها دون التطبيق.

المرقوم (Hashable): هو ما يقبل الإجراء hash() الذي يحول الشيء إلى رقم يرمز إليه. ومنه:

  • الرقم (int) رقْمه هو نفسه
  • النص (str) له خوارزمية معيَّنة لرقْمه (انظر هنا للاستزادة)
  • الصف (tuple) رقْمه هو رقم عناصره (فيجب أن تكون جميع عناصره مرقومة)

وهو بخلاف الجمع المرتَّب -كالقائمة التي سبقت دراستها-، حيث ترقيم عناصرها يكون بالموضع نسبة إلى موضع الأوَّل: 0 ثم 1 ثم 2 …إلخ. ولكون القائمة متغيرة (تقبل زيادة أو حذف أو تعديل عنصر) فإن رقمها غير ثابت، والشرط في المرقوم ألا يتغير رقمه أبدًا؛ لذا تجد الصف معدودًا ضمن المرقومات؛ لأنه الجامد لا يتغير بعد إنشائه.

نرى في المثال إمكان اختيار عناصر مرقومة للمجموعة بأنواع مختلفة:

s = {10, 'AAA', True, (22, 'BB')}

ونرى عمليات المجموعة عليها: العد، والعضوية والتكرار:

assert len(s) == 4
assert 10 in s
assert 22 not in s
assert (22, 'BB') in s

for x in s:
    print(x)
AAA
10
True
(22, 'BB')

باعتبارها مجموعة غير مرتبة، فإنها لا تسجل موقع العنصر أو ترتيب إدراجه. وبالتالي، فإنها لا تقبل الإشارة (xs[i]) أو التقطيع (xs[i:j]) أو أي سلوك يشبه المتسلسلات. لاحظ الخطأ التالي:

xs = {10, 20, 30}
xs[0]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[4], line 2
      1 xs = {10, 20, 30}
----> 2 xs[0]

TypeError: 'set' object is not subscriptable

منطق المجموعة الرياضية

وتقبل المجموعة الفريدة ما تقبله المجموعة في الرياضيات من عمليات:

  • التقاطع والاتحاد والفرق، والفرق التماثلي
  • وكذلك تحقق: (الجزئية والشمول والانفاصل).

وهذه القطعة مثال لجميع هذه العمليات الرياضية:

set1 = {1, 2, 3, 4, 5}
set2 =          {4, 5, 6, 7, 8}

اتحاد مجموعتين
set1 | set2
{1, 2, 3, 4, 5, 6, 7, 8}

تقاطع مجموعتين
set1 & set2
{4, 5}

الفرق
set1 - set2
{1, 2, 3}
set2 - set1
{6, 7, 8}

الفرق التماثلي
set1 ^ set2
{1, 2, 3, 6, 7, 8}

نصيحة: من الأفضل استعمال اسم الإجراء بدلاً من العلامة التي تقابله حيث أنها تقبل أي نوع من المتكررات (Iterables) ولا تقتصر على نوع المجموعة فقط (set). أي، استعمل ما يقابلها كما هو موضَّح في الجدول:

العملية العلامة الإجراء المكافئ
الاتحاد set1 | set2 set1.union(set2)
التقاطع set1 & set2 set1.intersection(set2)
الفرق set1 - set2 set1.difference(set2)
الفرق التماثلي set1 ^ set2 set1.symmetric_difference(set2)

وكذلك لدينا إجراءات تحقق الجزئية والشمول والانفصال:

العملية العلامة الإجراء المكافئ
تحقق الجزئية set1 <= set2 set1.issubset(set2)
تحقق الشمول set1 >= set2 set1.issuperset(set2)
تحقق الانفصال len(set1 & set2) == 0 set1.isdisjoint(set2)

الجزئية والشمول
A = {1, 2, 3}
B = {1, 2, 3, 4, 5, 6}

وهذا مثال لاستعمالها كما في الجدول:

assert A.issubset(B)
assert B.issuperset(A)

وأما الانفصال، فهو عدم وجود أدنى تقاطع بين المجموعتين:

C = {'Apple', 'Banana'}
assert C.isdisjoint(A)
assert C.isdisjoint(B)