آموزش مرتب سازی لیست در پایتون با ۲ روش

مرتب‌سازی لیست‌ها یکی از عملیات‌های کاربردی در برنامه‌نویسی است. در بسیاری از مواقع نیاز به مرتب کردن یکسری داده داریم؛ برای مثال، نمرات دانشجویان، قیمت‌ها، اسامی افراد. در این آموزش ۲ روش اصلی مرتب سازی لیست در زبان پایتون را آموزش می‌بینم. همچنین نحوه نزولی کردن و مرتب شدن بر اساس ویژگی خاص را بررسی می‌کنیم.

برای مرتب‌سازی داده‌ها در پایتون ۲ روش اصلی داریم. هر دو روش نتیجهٔ یکسانی دارند اما به روش‌های مختلفی این کار را انجام داده و البته رفتار متفاوتی با لیست اولیه دارند. در ادامه به بررسی هر کدام می‌پردازیم.

مرتب‌سازی لیست در پایتون

فرض کنید لیستی از اعداد داریم که باید آن‌ها را به ترتیب صعودی مرتب کنیم. اگر با لیست‌ها و ترفندهای آن آشنایی کافی ندارید، پیشنهاد می‌کنم جلسه لیست در پایتون را ببینید. دو روشی که برای مرتب‌سازی این اعداد داریم عبارت‌اند از:

  • متد sort : این مورد به‌صورت متدی روی شیء لیست فراخوانی شده و همان لیست را مرتب می‌کند.
  • تابع sorted : این تابع، لیست مورد نظر را به‌عنوان ورودی گرفته و یک نسخهٔ مرتب‌شده از آن را به ما برمی‌گرداند.

تفاوت اصلی و قابلِ توجه این دو روش این است که sort() لیست مورد نظر را تغییر داده و مرتب می‌کند؛ اما sorted() لیست اصلی را بدون تغییر رها کرده و لیست جدیدی را به‌صورت مرتب‌شده به ما می‌دهد. در ادامه آموزش با این تفاوت‌ها به‌طور کامل آشنا می‌شویم.

مرتب کردن لیست با sort()

متد sort() در پایتون، لیست را به‌صورت درجا (in-place) مرتب می‌کند. این متد هیچ مقداری را به‌عنوان خروجی برنمی‌گرداند. به عبارت دیگر، همان لیست را تغییر داده و به‌طور پیش‌فرض مقدار None را return می‌کند.

در قطعه کد زیر، لیستی از اعداد غیر مرتب داریم. در خط دوم، متد sort() را روی لیست فراخوانی کرده و در نهایت همان لیست را چاپ می‌کنیم. خروجی این قطعه کد، به‌صورت کامنت مشخص شده است. می‌بینید که همان متغیر تغییر کرده و دیگر به لیستِ غیر مرتب دسترسی نداریم.

numbers = [34, -10, 7, 56, 3, 87, 12, 0]
numbers.sort()
print(numbers)

# output: [-10, 0, 3, 7, 12, 34, 56, 87]

اگر اعضای لیست ما رشته باشند، این مقادیر بر اساس ترتیب حروف الفبا مرتب می‌شوند. همان‌طور که از آموزش رشته در پایتون می‌دانید، می‌توانیم رشته‌های فارسی نیز داشته باشیم. بنابراین اگر لیستی از اسامی فارسی یا انگلیسی داشته باشیم، می‌توانیم با فراخوانی متد sort() آن‌ها را به ترتیب حروف الفبا مرتب کنیم.

names = ["Mona", "Omid", "Sara", "Ehsan"]
names.sort()
print(names)

# output: ['Ehsan', 'Mona', 'Omid', 'Sara']

متد sort() روی لیست صدا زده می‌شود و همان لیست را مرتب می‌کند. بنابراین لیست نامرتب را از دست می‌دهیم و به‌جایش مرتب‌شده را خواهیم داشت.

مرتب‌سازی با sorted() پایتون

تابع sorted() مشابه متد sort() عمل می‌کند، با این تفاوت که به‌جای تغییر لیست اصلی، یک کپی از آن ایجاد کرده و مرتب‌سازی را روی لیست جدید انجام می‌دهد. با این تفسیر، این تابع لیست مرتب‌شده را به‌عنوان خروجی return می‌کند.

دقت کنید که باید مقدار خروجی این تابع را درون یک متغیر قرار داده و سپس از آن استفاده کنیم. (بیشتر بخوانید: تعریف متغیر در پایتون)

در قطعه کد زیر، همان لیست اعدادی که بالاتر داشتیم را با تابع sorted() مرتب می‌کنم. در نهایت هر دو متغیر لیست اولی و لیستی که مرتب شده را پرینت کرده‌ام.

numbers = [34, -10, 7, 56, 3, 87, 12, 0]
sorted_numbers = sorted(numbers)
print(sorted_numbers)
print(numbers)

خروجی کد بالا چیزی شبیه به تصویر زیر خواهد شد. لیست اول لیست جدیدی است که مرتب شده و لیست دوم همان لیست اولیه است که بدون تغییر باقی مانده است.

خروجی مرتب کردن لیست عددی با تابع sorted
خروجی مرتب کردن لیست عددی با تابع sorted پایتون

به‌طور مشابه، اگر لیستی از رشته‌ها داشته باشیم نیز عملیات مرتب‌سازی لیست پایتون انجام می‌شود.

names = ["Mona", "Omid", "Sara", "Ehsan"]
sorted_names = sorted(names)
print(sorted_names)
print(names)

# ['Ehsan', 'Mona', 'Omid', 'Sara']
# ['Mona', 'Omid', 'Sara', 'Ehsan']

تابع sorted() یک کپی از لیست می‌گیرد و نسخه‌ی کپی را مرتب می‌کند. بنابراین لیست نامرتب قدیمی همچنان باقی مانده و باید خروجی این تابع را درون یک متغیر دلخواه قرار دهیم.

مرتب کردن نزولی لیست پایتون

به‌طور پیش‌فرض مرتب‌سازی داده‌ها به‌صورت صعودی است. یعنی از عدد کوچک‌تر تا بزرگ‌تر و از حروف A تا Z. گاهی لازم داریم تا عملیات مرتب کردن لیست پایتون نزولی انجام شود. یکی از راه‌حل‌های اولیه که ممکن است به ذهنمان برسد، این است که ابتدا لیست را مرتب کنیم و سپس آن را معکوس کنیم. (برای معکوس کردن می‌توان از متد reverse() یا نوشتن یک حلقه در پایتون کمک گرفت.)

اما روش ساده‌تری نیز داریم. برای مرتب‌سازی نزولی، می‌توان از پارامتر reverse=True در sort() و sorted() استفاده کرد. مقدار پارامتر reverse به‌طور پیش‌فرض False است و به همین دلیل مرتب‌سازی به‌صورت صعودی انجام می‌شود. وقتی مقدار این پارامتر را به True تغییر می‌دهیم، عملیات مرتب کردن نزولی می‌شود.

numbers = [34, -10, 7, 56, 3, 87, 12, 0]
numbers.sort(reverse=True)
print(numbers)

# output: [87, 56, 34, 12, 7, 3, 0, -10]

به‌طور مشابه، در قطعه کد زیر از پارامتر reverse در تابع sorted() استفاده کرده‌ام:

names = ["Mona", "Omid", "Sara", "Ehsan"]
sorted_names_desc = sorted(names, reverse=True)
print(sorted_names_desc)

# output: ['Sara', 'Omid', 'Mona', 'Ehsan']
List Comprehension در پایتون : آموزش و نکات کاربردی آن

List Comprehension در پایتون : آموزش و نکات کاربردی آن

مرتب سازی لیست با ویژگی دلخواه

گاهی لازم داریم عملیات مرتب سازی لیست در پایتون بر اساس یک ویژگی خاص انجام شود. برای مثال موارد زیر را در نظر بگیرید:

  • مرتب‌سازی اعداد بر اساس قد مطلق آن‌ها (فقط مقدار عددی، بدون توجه به مثبت یا منفی بودن)
  • مرتب‌سازی لیستی از رشته‌ها بر اساس طول هر رشته
  • مرتب کردن داده‌ها بر اساس مقادیر خاص درون ساختارهای پیچیده (برای مثال، لیستی از دیکشنری‌ها)

در این‌گونه موارد از پارامتر key در متد sort() و تابع sorted() استفاده می‌کنیم. پارامتر key به ما اجازه می‌دهد تا لیست را بر اساس یک ویژگی خاص مرتب کنیم.

پارامتر key نام یک تابع را گرفته و بر روی تمام داده‌ها اعمال می‌کند. سپس اعضای لیست را بر اساس مقداری که متناسب با هر کدام (با اعمال تابع مورد نظر روی آن) برگردانده شده است مرتب می‌کند.

بیایید یک مثال بزنم. فرض کنید لیستی از رشته‌های متنی داریم. من از چهار اسم استفاده می‌کنم. مثلاً:

names = ["Sara", "Farahad", "Atena", "Mohammad"]

حال می‌خواهیم این اسامی بر اساس طول (تعداد حروف) مرتب شوند. برای این کار از متد sort() با key=len استفاده می‌کنم. منظور از len همان تابع len() است که اندازه رشته را به ما برمی‌گرداند.

names = ["Sara", "Farahad", "Atena", "Mohammad"]
names.sort(key=len)
print(names)

# output: ['Sara', 'Atena', 'Farahad', 'Mohammad']

همان‌طور که در خط آخر باکس بالا می‌بینید، لیست مرتب‌شده‌ی ما بر اساس طول رشته‌ها و صعودی است. می‌توانستیم به‌طور ترکیبی از پارامتر key و reverse استفاده کنیم.

در قطعه کد زیر، اعداد را بر اساس مقدار قدر مطلق آن‌ها مرتب می‌کنم. برای اینکه ببینید از key می‌توان در تابع sorted() نیز استفاده کرد، اینجا از این تابع استفاده می‌کنم:

numbers = [34, -10, 7, -56, 3, -87, 12, 0]
custom_sorted_numbers = sorted(numbers, key=abs)
print(custom_sorted_numbers)

# output: [0, 3, 7, -10, 12, 34, -56, -87]

مرتب سازی لیستی از دیکشنری در پایتون

تابعی که به پارامتر key می‌دهیم می‌تواند از توابع built-in پایتون بوده یا از توابعی باشد که توسط خودمان نوشته شده‌اند. یک مثال کمی پیچیده‌تر را در نظر بگیرید:

فرض کنید لیستی از دیکشنری‌ها داریم. هر دیکشنری نام و نمره یک دانشجو را مشخص می‌کند.

students = [{"name": "Nazanin", "score": 15},
            {"name": "Negar", "score": 18.5},
            {"name": "Alireza", "score": 16.5},
            {"name": "Mohsen", "score": 18}]

حال می‌خواهیم مرتب سازی لیست را بر اساس نمرات دانشجویان با پایتون انجام دهیم. برای این کار، ابتدا باید تابعی بنویسیم که وقتی یکی از اعضای این لیست را به‌عنوان ورودی می‌گیرد، نمره‌اش را به ما برگرداند. اگر با توابع آشنا نیستید، پیشنهاد می‌کنم ویدئوی آموزش تابع در پایتون را ببینید.

def get_score(student):
    return student['score']

حال کافی است این تابع را برای مقدار پارامتر key تعریف کنیم. چون می‌خواهم دانشجویان از نمره بیشتر به کمتر (نزولی) مرتب شوند، پارامتر reverse را نیز تعریف می‌کنم:

students.sort(reverse=True, key=get_score)

اگر مقدار students را پرینت کنم، لیستی شبیه به لیست تصویر زیر خواهم داشت:

نتیجه مرتب کردن لیستی از دیکشنری‌ها با کلید خاص
نتیجه مرتب کردن لیستی از دیکشنری‌ها با کلید خاص

خلاصه آموزش

در این آموزش با ۲ روش اصلی مرتب سازی لیست در پایتون آشنا شدیم. متد sort() مستقیماً لیست اصلی را تغییر می‌دهد درحالی‌که تابع sorted() یک نسخه جدید را ایجاد کرده و آن را مرتب می‌کند. همچنین نحوه استفاده از پارامتر reverse برای نزولی کردن عملیات مرتب‌سازی و پارامتر key برای مرتب‌سازی بر اساس ویژگی دلخواه را بررسی کردیم. می‌توانید مستندات مرتب کردن لیست در پایتون را از اینجا ببینید.

پیشنهاد می‌کنم، یک لیست تو در تو ایجاد کنید. لیست‌ها درونی باید همگی ساختار مشابهی داشته باشند. اکنون سعی کنید بر اساس یکی از اندیس‌های لیست‌های درونی، مرتب‌سازی لیست اصلی را انجام دهید. کد شما چیزی شبیه به مثال آخر (دیکشنری) می‌شود با این تفاوت که در تابع get_score() باید با یک لیست به‌جای دیکشنری کار کنید.