طريقة مصفوفة قائمة فرز بايثون - شرح تصاعدي وتنازلي بأمثلة

إذا كنت تريد معرفة كيفية التعامل مع sort()الطريقة في مشاريع Python ، فهذه المقالة مناسبة لك. هذه الطريقة قوية للغاية ويمكنك تخصيصها لتناسب احتياجاتك ، لذلك دعونا نرى كيف تعمل بالتفصيل.

سوف تتعلم:

  • كيفية استخدام هذه الطريقة وتخصيص وظائفها.
  • متى يتم استخدامها ومتى لا تستخدمها.
  • كيف نسميها تمرير مجموعات مختلفة من الحجج.
  • كيفية فرز القائمة بترتيب تصاعدي وتنازلي.
  • كيفية مقارنة عناصر القائمة بناءً على القيم الوسيطة.
  • كيف يمكنك تمرير وظائف لامدا لهذه الطريقة.
  • كيف تقارن هذه الطريقة sorted()بالوظيفة.
  • لماذا sort()تقوم الطريقة بفرز مستقر.
  • كيف تعمل عملية الطفرة خلف الكواليس.

هل أنت جاهز؟ هيا نبدأ! ⭐

? حالات الغرض والاستخدام

باستخدام sort()الطريقة ، يمكنك فرز القائمة إما:

  • ترتيب تصاعدي
  • تنازليا

تُستخدم هذه الطريقة لفرز القائمة في مكانها ، مما يعني أنها تقوم بتحويرها أو تعديلها مباشرةً دون إنشاء نسخ إضافية ، لذا تذكر:

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

لهذا السبب ، يجب ألا تستخدم هذه الطريقة إلا إذا:

  • تريد تعديل (فرز) القائمة بشكل دائم.
  • لست بحاجة إلى الاحتفاظ بالنسخة الأصلية من القائمة.

إذا كان هذا يناسب احتياجاتك ، فإن .sort()الطريقة هي بالضبط ما تبحث عنه.

النحو والحجج

دعونا نرى كيف يمكنك الاتصال .sort()للاستفادة من قوتها الكاملة.

هذه هي المكالمة الأساسية (بدون وسيطات):

إذا لم تمرر أي وسيطات ، بشكل افتراضي:

  • سيتم فرز القائمة بترتيب تصاعدي.
  • ستتم مقارنة عناصر القائمة مباشرة باستخدام قيمها مع <عامل التشغيل.

فمثلا:

>>> b = [6, 3, 8, 2, 7, 3, 9] >>> b.sort() >>> b [2, 3, 3, 6, 7, 8, 9] # Sorted!

الحجج المخصصة  

لتخصيص كيفية عمل sort()الطريقة ، يمكنك تمرير وسيطتين اختياريتين:

  • مفتاح
  • يعكس

دعونا نرى كيف يغيرون سلوك هذه الطريقة. هنا لدينا عملية استدعاء مع هاتين الوسيطتين:

قبل شرح كيفية عملها ، أود أن أشرح شيئًا ربما لاحظته في الرسم التخطيطي أعلاه - في استدعاء الأسلوب ، يجب تضمين أسماء المعلمات قبل القيم المقابلة لها ، مثل هذا:

  • key=
  • reverse=

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

بخلاف ذلك ، إذا حاولت تمرير الوسائط مباشرةً كما نفعل عادةً مع المعلمات الموضعية ، فسترى هذا الخطأ لأن الوظيفة لن تعرف الوسيطة التي تتوافق مع أي معلمة:

TypeError: sort() takes no positional arguments

يعكس

الآن بعد أن تعرفت على وسيطات الكلمات الرئيسية فقط ، فلنبدأ بها reverse.

reverseيمكن أن تكون قيمة إما Trueأو False:

  • False يعني أنه سيتم فرز القائمة بترتيب تصاعدي.
  • True يعني أنه سيتم فرز القائمة بترتيب تنازلي (عكسي).

? تلميح: القيمة الافتراضية هي False- إذا لم تمرر أي وسيطات لهذا المعامل ، فسيتم فرز القائمة بترتيب تصاعدي.

هنا لدينا بعض الأمثلة:

# List of Integers >>> b = [6, 3, 8, 2, 7, 3, 9] >>> b.sort() >>> b [2, 3, 3, 6, 7, 8, 9] # List of Strings >>> c = ["A", "Z", "D", "T", "U"] >>> c.sort() >>> c ['A', 'D', 'T', 'U', 'Z'] 

? نصيحة: إذا كانت عناصر القائمة عبارة عن سلاسل ، فسيتم فرزها أبجديًا.

# List of Integers >>> b = [6, 3, 8, 2, 7, 3, 9] >>> b.sort(reverse=True) >>> b [9, 8, 7, 6, 3, 3, 2] # List of Strings >>> c = ["A", "Z", "D", "T", "U"] >>> c.sort(reverse=True) >>> c ['Z', 'U', 'T', 'D', 'A']

? نصيحة: لاحظ كيف يتم فرز القائمة بترتيب تنازلي إذا reverseهو True.

مفتاح

الآن بعد أن عرفت كيفية التعامل مع reverseالمعلمة ، دعنا نرى keyالمعلمة.

هذه المعلمة أكثر تفصيلاً قليلاً لأنها تحدد كيفية مقارنة عناصر القائمة أثناء عملية الفرز.

قيمة keyإما:

  • None, which means that the elements of the list will be compared directly. For example, in a list of integers, the integers themselves can be used for the comparison.
  • Afunction of one argument that generates an intermediate value for each element. This intermediate value is calculated only once and it's used to make the comparisons during the entire sorting process. We use this when we don't want to compare the elements directly, for example, when we want to compare strings based on their length (the intermediate value).

? Tip: By default, the value of key is None, so the elements are compared directly.

For example:

Let's say that we want to sort a list of strings based on their length, from the shortest string to the longest string. We can pass the function len as the value of key, like this:

>>> d = ["aaa", "bb", "c"] >>> d.sort(key=len) >>> d ['c', 'bb', 'aaa']

? Tip: Notice that we are only passing the name of the function (len) without parenthesis because we are not calling the function. This is very important.

Notice the difference between comparing the elements directly and comparing their length (see below). Using the default value of key (None) would have sorted the strings alphabetically (left), but now we are sorting them based on their length (right):

What happens behind the scenes? Each element is passed as an argument to the len() function, and the value returned by this function call is used to perform the comparisons during the sorting process:

This results in a list with a different sorting criteria: length.

Here we have another example:

Another interesting example is sorting a list of strings as if they were all written in lowercase letters (for example, making "Aa" equivalent to "aa").

According to lexicographical order, capital letters come before lowercase letters:

>>> "E" < "e" True

So the string "Emma" would come before "emily" in a sorted list, even if their lowercase versions would be in the opposite order:

>>> "Emma" >> "emma" < "emily" False

To avoid distinguishing between capital and lowercase letters, we can pass the function str.lower as key. This will generate a lowercase version of the strings that will be used for the comparisons:

>>> e = ["Emma", "emily", "Amy", "Jason"] >>> e.sort(key=str.lower) >>> e ['Amy', 'emily', 'Emma', 'Jason']

Notice that now, "emily" comes before "Emma" in the sorted list, which is exactly what we wanted.

? Tip: if we had used the default sorting process, all the strings that started with an uppercase letter would have come before all the strings that started with a lowercase letter:

>>> e = ["Emma", "emily", "Amy", "Jason"] >>> e.sort() >>> e ['Amy', 'Emma', 'Jason', 'emily']

Here is an example using Object-Oriented Programming (OOP):

If we have this very simple Python class:

>>> class Client: def __init__(self, age): self.age = age

And we create four instances:

>>> client1 = Client(67) >>> client2 = Client(23) >>> client3 = Client(13) >>> client4 = Client(35)

We can make a list that references them:

>>> clients = [client1, client2, client3, client4]

Then, if we define a function to get the age of these instances:

>>> def get_age(client): return client.age

We can sort the list based on their age by passing the get_age function an an argument:

>>> clients.sort(key=get_age)

This is the final, sorted version of the list. We use a for loop to print the age of the instances in the order that they appear in the list:

>>> for client in clients: print(client.age) 13 23 35 67

Exactly what we wanted – now the list is sorted in ascending order based on the age of the instances.

? Tip: Instead of defining a get_age function, we could have used a lambda function to get the age of each instance, like this:

>>> clients.sort(key=lambda x: x.age)

Lambda functions are small and simple anonymous functions, which means that they don't have a name. They are very helpful for these scenarios when we only want to use them in particular places for a very short period of time.

This is the basic structure of the lambda function that we are using to sort the list:

Passing Both Arguments

Awesome! Now you know to customize the functionality of the sort() method. But you can take your skills to a whole new level by combining the effect of key and reverse in the same method call:

>>> f = ["A", "a", "B", "b", "C", "c"] >>> f.sort(key=str.lower, reverse=True) >>> f ['C', 'c', 'B', 'b', 'A', 'a']

These are the different combinations of the arguments and their effect:

The Order of Keyword-Only Arguments Doesn't Matter

Since we are specifying the names of the arguments, we already know which value corresponds to which parameter, so we can include either key or reverse first in the list and the effect will be exactly the same.

So this method call:

Is equivalent to:

This is an example:

>>> a = ["Zz", "c", "y", "o", "F"] >>> a.sort(key=str.lower, reverse=True) >>> a ['Zz', 'y', 'o', 'F', 'c']

If we change the order of the arguments, we get the exact same result:

>>> a = ["Zz", "c", "y", "o", "F"] >>> a.sort(reverse=True, key=str.lower) >>> a ['Zz', 'y', 'o', 'F', 'c']

? Return Value

الآن دعنا نتحدث قليلاً عن القيمة المعادة لهذه الطريقة. ل sort()إرجاع الأسلوب None- فإنه لا يعود نسخة فرز القائمة، مثل يمكننا أن نتوقع بشكل حدسي.

وفقًا لتوثيق بايثون:

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

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

هذا مثال على قيمة إرجاع sort():

>>> nums = [6.5, 2.4, 7.3, 3.5, 2.6, 7.4] # Assign the return value to this variable: >>> val = nums.sort() # Check the return value: >>> print(val) None

نرى؟ Noneتم إرجاعه بواسطة استدعاء الأسلوب.

? Tip: It is very important not to confuse the sort() method with the sorted() function, which is a function that works very similarly, but doesn't modify the original list. Instead sorted() generates and returns a new copy of the list, already sorted.

This is an example that we can use to compare them:

# The sort() method returns None >>> nums = [6.5, 2.4, 7.3, 3.5, 2.6, 7.4] >>> val = nums.sort() >>> print(val) None
# sorted() returns a new sorted copy of the original list >>> nums = [6.5, 2.4, 7.3, 3.5, 2.6, 7.4] >>> val = sorted(nums) >>> val [2.4, 2.6, 3.5, 6.5, 7.3, 7.4] # But it doesn't modify the original list >>> nums [6.5, 2.4, 7.3, 3.5, 2.6, 7.4]

This is very important because their effect is very different. Using the sort() method when you intended to use sorted() can introduce serious bugs into your program because you might not realize that the list is being mutated.

? The sort() Method Performs a Stable Sort

Now let's talk a little bit about the characteristics of the sorting algorithm used by sort().

تؤدي هذه الطريقة فرزًا مستقرًا لأنها تعمل مع تطبيق TimSort ، وهي خوارزمية فرز فعالة ومستقرة للغاية.

وفقًا لتوثيق بايثون:

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

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

دعونا نرى ما أعنيه بهذا. يرجى إلقاء نظرة على هذا المثال لبضع لحظات:

>>> d = ["BB", "AA", "CC", "A", "B", "AAA", "BBB"] >>> d.sort(key=len) >>> d ['A', 'B', 'BB', 'AA', 'CC', 'AAA', 'BBB']

نحن نقارن العناصر بناءً على طولها لأننا مررنا lenالدالة كوسيطة لـ key.

We can see that there are three elements with length 2: "BB", "AA", and "CC" in that order.

Now, notice that these three elements are in the same relative order in the final sorted list:

This is because the algorithm is guaranteed to be stable and the three of them had the same intermediate value (key) during the sorting process (their length was 2, so their key was 2).

? Tip: The same happened with "A" and "B" (length 1) and "AAA" and "BBB" (length 3), their original order relative to each other was preserved.

Now you know how the sort() method works, so let's dive into mutation and how it can affect your program.

? Mutation and Risks

As promised, let's see how the process of mutation works behind the scenes:

When you define a list in Python, like this:

a = [1, 2, 3, 4]

You create an object at a specific memory location. This location is called the "memory address" of the object, represented by a unique integer called an id.

You can think of an id as a "tag" used to identify a specific place in memory:

You can access a list's id using the id() function, passing the list as argument:

>>> a = [1, 2, 3, 4] >>> id(a) 60501512

When you mutate the list, you change it directly in memory. You may ask, why is this so risky?

It's risky because it affects every single line of code that uses the list after the mutation, so you may be writing code to work with a list that is completely different from the actual list that exists in memory after the mutation.

This is why you need to be very careful with methods that cause mutation.

In particular, the sort() method mutates the list. This is an example of its effect:

Here is an example:

# Define a list >>> a = [7, 3, 5, 1] # Check its id >>> id(a) 67091624 # Sort the list using .sort() >>> a.sort() # Check its id (it's the same, so the list is the same object in memory) >>> id(a) 67091624 # Now the list is sorted. It has been mutated! >>> a [1, 3, 5, 7]

The list was mutated after calling .sort().

Every single line of code that works with list a after the mutation has occurred will use the new, sorted version of the list. If this was not what you intended, you may not realize that other parts of your program are working with the new version of the list.

Here is another example of the risks of mutation within a function:

# List >>> a = [7, 3, 5, 1] # Function that prints the elements of the list in ascending order. >>> def print_sorted(x): x.sort() for elem in x: print(elem) # Call the function passing 'a' as argument >>> print_sorted(a) 1 3 5 7 # Oops! The original list was mutated. >>> a [1, 3, 5, 7]

The list a that was passed as argument was mutated, even if that wasn't what you intended when you initially wrote the function.

? Tip: If a function mutates an argument, it should be clearly stated to avoid introducing bugs into other parts of your program.

? Summary of the sort() Method

  • The sort() method lets you sort a list in ascending or descending order.
  • It takes two keyword-only arguments: key and reverse.
  • reverse determines if the list is sorted in ascending or descending order.
  • key is a function that generates an intermediate value for each element, and this value is used to do the comparisons during the sorting process.
  • The sort() method mutates the list, causing permanent changes. You need to be very careful and only use it if you do not need the original version of the list.

آمل حقًا أن تكون مقالتي قد أعجبتك ووجدتها مفيدة. يمكنك الآن العمل بهذهsort()الطريقة في مشاريع Python الخاصة بك. تحقق من دوراتي عبر الإنترنت. تابعني على تويتر. ⭐️