اذهب إلى المحتوى

السؤال

نشر

السلام عليكم،

لدي مصفوفة من العناصر و كل عنصر من الممكن أن يكون بحد ذاته مصفوفة، و ذلك يتكرر إلى عمق غير معروف.

أي مثلاً هذه المصفوفة

a = [[1, 2], [3, 4, [5, 6, [7]], 8], 9, [10, 11, [12, [13, [14], 15], 16], 17]]

أي أن الدخل سيكون مثل المصفوفة السابقة و علي فكها إلى مصفوفة واحدة من الأرقام.

أعلم كيفية حل المشكلة السابقة باستعمال تابع يستدعي نفسه، و لكن هل هنالك طريقة أخرى أو تابع جاهز يقوم بذلك؟

Recommended Posts

  • 1
نشر

في أغلب الأحيان يمكن تحويل نفس الفكرة الخاصة بالتابع الذي يستدعي نفسه إلى حلقة تكرارية.

يمكننا أن نقوم بالعمليات مستوى مستوى، أي أن نقوم في البداية بفك أول مستوى ثم ثاني مستوى و هكذا حتى النهاية.

كيف سنعلم أننا انتهينا؟ يمكننا تخزين ذلك في متحول في حال قمنا بفك أي شيء نقوم بإسناد قيمة معينة إليه تدلنا على ذلك، و في حال انتهينا و لم نسند له شيء فهذا يدل على أننا لم نقم بفك أي مصفوفة و بالتالي انتهينا من فك كل المستويات.

أحد الطرق لكتابة الكود السابق هو كالتالي:

a = [[1, 2], [3, 4, [5, 6, [7]], 8], 9, [10, 11, [12, [13, [14], 15], 16], 17]]


while True:
  flg = True
  new_a = []
  for item in a:
    if type(item) is list:
      flg = False
      new_item = item
    else:
      new_item = [item]
    new_a.extend(new_item)
  a = new_a
  if flg:
    break
print(a)

هنا نقوم بكتابة حلفة لا نهائية أي أنها ستظل تكرر نفسها، و لكن سنستعمل break لإيقافها عند تحقق شرط ما.

في البداية نقوم بتخزين قيمة True في متحول للدلالة على أننا انتهينا، و في حال قمنا بأي تعديل سنعدل قيمته إلى False أي أننا لم ننته.

أيضاً نقوم بتعريف مصفوفة جديدة لتخزين الناتج فيها.

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

في حال لم يكن list فنقوم بوضعه في list.

لقد قمنا بالعملية السابقة لتسهيل كيفية الإضافة إلى المصفوفة الجديدة، حيث يمكننا الآن استدعاء التابع extend فقط، و هو سيضيف كافة العناصر إلى المصفوفة الجديدة، أي في حال كان العنصر بالأصل list سيقوم بإضافة العناصر داخل هذه ال list و في حال لم يكن كذلك سيضيف العنصر كما هو.

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

بالطبع يمكننا تحسين الكود السابق ليصبح أسرع، سأترك لك هذه المهمة لتحاول فيها و يمكنك السؤال مجدداً في حال لم تستطع ذلك.

  • 1
نشر

الحل الأمثل في مثل هذه الحالة هو إستعمال recursive method طالما أن نوع السلسلة متعدد المستويات من العمق  multiple levels depth. إليك المثال التالي

my_list = [[1, 2], [3, 4, [5, 6, [7]], 8], 9, [10, 11, [12, [13, [14], 15], 16], 17]]
def flatten(L):
    if not isinstance(L,(list)): # إذا لم يكن المدخل الحالي قيد المعالجة من النوع سلسلة
        yield L  
        # generator object نعيد
        return
    for F in L: # نمر في حلقة تكرار على المدخل
        yield from flatten(F)  # نعيد الناتج ونستمر بالإرجاع لحين المرور على جميع العناصر

flat= list(flatten(my_list)) #  نستدعي الدالة ونحول الى سلسلة

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

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...