الفرز في بايثون

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

  a = [5, 1, 4, 3]
  print(sorted(a))  ## [1, 3, 4, 5]
  print(a)  ## [5, 1, 4, 3]

من الأكثر شيوعًا لتمرير قائمة إلى الدالة sorted()، ولكن في الواقع يمكن أن تأخذ كمدخلات أي نوع من المجموعات القابلة للتكرار. طريقة list.sort() الأقدم هي طريقة بديلة مفصلة أدناه. تبدو الدالة sorted() أسهل في الاستخدام مقارنة بـ sorted()، لذلك أوصي باستخدام sorted().

يمكن تخصيص الدالة sorted() من خلال الوسيطات الاختيارية. الوسيطة الاختيارية sorted() العكسية=True، على سبيل المثال sorted(list, violation=True)، تجعلها تؤدي إلى الفرز للخلف.

  strs = ['aa', 'BB', 'zz', 'CC']
  print(sorted(strs))  ## ['BB', 'CC', 'aa', 'zz'] (case sensitive)
  print(sorted(strs, reverse=True))   ## ['zz', 'aa', 'CC', 'BB']

تصنيف مخصّص باستخدام المفتاح=

للحصول على فرز مخصص أكثر تعقيدًا، تأخذ sorted() دالة "key=" اختيارية تحدد دالة "key" التي تحول كل عنصر قبل المقارنة. تستخدم الدالة الأساسية قيمة واحدة وتعرض قيمة واحدة، ويتم استخدام قيمة "الخادم الوكيل" المعروضة للمقارنات ضمن الفرز.

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

  strs = ['ccc', 'aaaa', 'd', 'bb']
  print(sorted(strs, key=len))  ## ['d', 'bb', 'ccc', 'aaaa']

تم ترتيب الاستدعاء باستخدام key=len

كمثال آخر، يعد تحديد "str.lower" كدالة أساسية طريقة لفرض الترتيب على التعامل مع الأحرف الكبيرة والصغيرة بالطريقة نفسها:

  ## "key" argument specifying str.lower function to use for sorting
  print(sorted(strs, key=str.lower))  ## ['aa', 'BB', 'CC', 'zz']

يمكنك أيضًا تمرير MyFn الخاص بك كدالة رئيسية، على النحو التالي:

  ## Say we have a list of strings we want to sort by the last letter of the string.
  strs = ['xc', 'zb', 'yd' ,'wa']

  ## Write a little function that takes a string, and returns its last letter.
  ## This will be the key function (takes in 1 value, returns 1 value).
  def MyFn(s):
    return s[-1]

  ## Now pass key=MyFn to sorted() to sort by the last letter:
  print(sorted(strs, key=MyFn))  ## ['wa', 'zb', 'xc', 'yd']

للحصول على ترتيب أكثر تعقيدًا مثل الترتيب حسب اسم العائلة ثم الاسم الأول، يمكنك استخدام دالتَي itemgetter أو attrgetter، مثل:

  from operator import itemgetter

  # (first name, last name, score) tuples
  grade = [('Freddy', 'Frank', 3), ('Anil', 'Frank', 100), ('Anil', 'Wang', 24)]
  sorted(grade, key=itemgetter(1,0))
  # [('Anil', 'Frank', 100), ('Freddy', 'Frank', 3), ('Anil', 'Wang', 24)]

  sorted(grade, key=itemgetter(0,-1))
  #[('Anil', 'Wang', 24), ('Anil', 'Frank', 100), ('Freddy', 'Frank', 3)]

طريقة sort()

كبديل لـ sorted()، تقوم طريقة sort() في القائمة بفرز القائمة بترتيب تصاعدي، على سبيل المثال، list.sort(). تُغير طريقة sort() القائمة الأساسية وترجع None (بدون)، لذا يمكنك استخدامها على النحو التالي:

  alist.sort()            ## correct
  alist = blist.sort()    ## Incorrect. sort() returns None

ما ورد أعلاه هو سوء فهم شائع جدًا مع sort() -- حيث *لا يعرض* القائمة التي تم فرزها. يجب استدعاء طريقة sort() في قائمة؛ فهي لا تعمل على أي مجموعة enumerable (لكن الدالة sorted() أعلاه تعمل على أي شيء). تسبق طريقة sorted() الدالة sorted()، لذلك من المحتمل أن تراها في التعليمات البرمجية القديمة. لا تحتاج طريقة sort() إلى إنشاء قائمة جديدة، لذلك يمكن أن تكون أسرع قليلاً في حالة وجود العناصر المراد فرزها بالفعل في قائمة.

الصفوف

الصف هو مجموعة عناصر ذات حجم ثابت، مثل التناسق (س، ص). تشبه الصفوف القوائم، باستثناء أنها غير قابلة للتغيير ولا تتغير في الحجم (الصفوف غير قابلة للتغيير تمامًا لأن أحد العناصر المضمنة يمكن أن يكون قابلاً للتغيير). تلعب الصفوف دورًا "الهيكل" في بايثون - وهي طريقة ملائمة لتمرير مجموعة من القيم المنطقية وثابتة الحجم. يمكن للدالة التي تحتاج إلى عرض قيم متعددة أن تُرجع فقط صفًا من القيم. على سبيل المثال، إذا أردت الحصول على قائمة من الإحداثيات الثلاثية الأبعاد، فسيكون تمثيل بايثون الطبيعي عبارة عن قائمة من الصفوف، حيث يكون كل صف بحجم 3 مع مجموعة واحدة (س، ص، ع).

لإنشاء صف، ما عليك سوى إدراج القيم الموجودة بين الأقواس المفصولة بفواصل. إن الصف "الفارغ" ما هو إلا زوج فارغ من الأقواس. يشبه الوصول إلى العناصر في الصف القائمة تمامًا -- len(), [ ], for, in, وغيرها. تعمل جميعها بالطريقة نفسها.

  tuple = (1, 2, 'hi')
  print(len(tuple))  ## 3
  print(tuple[2])    ## hi
  tuple[2] = 'bye'  ## NO, tuples cannot be changed
  tuple = (1, 2, 'bye')  ## this works

لإنشاء صف الحجم-1، يجب أن يتبع العنصر الوحيد فاصلة.

  tuple = ('hi',)   ## size-1 tuple

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

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

  (x, y, z) = (42, 13, "hike")
  print(z)  ## hike
  (err_string, err_code) = Foo()  ## Foo() returns a length-2 tuple

استيعاب القائمة (اختياري)

ميزة فهم القوائم هي ميزة أكثر تقدمًا وهي مناسبة لبعض الحالات ولكنها ليست ضرورية للتمارين الرياضية وهي لا تحتاج إلى تعلمها في البداية (أي يمكنك تخطي هذا القسم). فهم القائمة هو طريقة مضغوطة لكتابة تعبير يتوسع إلى قائمة كاملة. لنفترض أن لدينا أرقام قائمة [1، 2، 3، 4]، إليك طريقة فهم القائمة لحساب قائمة بمربعاتها [1، 4، 9، 16]:

  nums = [1, 2, 3, 4]

  squares = [ n * n for n in nums ]   ## [1, 4, 9, 16]

البنية هي [ expr for var in list ]. ويبدو for var in list مثل التكرار الحلقي العادي، ولكن بدون علامة النقطتين (:). يتم تقييم expr على يساره مرة واحدة لكل عنصر من أجل توفير قيم القائمة الجديدة. في ما يلي مثال حول السلاسل، حيث يتم تغيير كل سلسلة إلى أحرف كبيرة مع إلحاق "!!!":

  strs = ['hello', 'and', 'goodbye']

  shouting = [ s.upper() + '!!!' for s in strs ]
  ## ['HELLO!!!', 'AND!!!', 'GOODBYE!!!']

يمكنك إضافة اختبار if على يمين الحلقة for-loop لتضييق نطاق النتيجة. يتم تقييم اختبار if لكل عنصر، بما في ذلك العناصر التي يكون الاختبار صحيحًا فقط.

  ## Select values <= 2
  nums = [2, 8, 1, 6]
  small = [ n for n in nums if n <= 2 ]  ## [2, 1]

  ## Select fruits containing 'a', change to upper case
  fruits = ['apple', 'cherry', 'banana', 'lemon']
  afruits = [ s.upper() for s in fruits if 'a' in s ]
  ## ['APPLE', 'BANANA']

تمرين: list1.py

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