نحوۀ مرتب کردن یک لیست در زبان برنامه‌نویسی پایتون


در آموزش‌های گذشته با مفهوم لیست و نحوۀ تعریف آبجکت‌هایی از جنس لیست آشنا شدیم و دیدیم که در تمامی مثال‌های مربوطه، هر یک از آیتم‌های داخل یک لیست بر اساس اندیسی مشخص درون آن جای می‌گیرند. حال فرض کنید آبجکتی از نوع لیست تحت عنوان list1 تعریف کرده‌ایم که دیتا تایپ تمامی اعضای آن استرینگ است:

>>> list1 = ['s', 'r', 'f', 'g', 'n', 'b']

همان‌طور که می‌دانیم، آیتم اول از لیست فوق با اندیس 0 مشخص شده و استرینگ «s» به آن اختصاص یافته است و به همین ترتیب آیتم پایانی لیست با اندیس 5 مشخص می‌شود که استرینگ «b» در آن جای گرفته است. زبان برنامه‌نویسی پایتون فانکشنی به اصطلاح Built-in تحت عنوان ()sort دارا است که امکان مرتب کردن آیتم‌های داخلی آبجکت‌هایی از جنس لیست را برای دولوپرهای این زبان فراهم می‌کند و از همین روی اگر بخواهیم لیست فوق‌الذکر را مرتب کنیم، فانکشن ()sort را روی آبجکت list1 به صورت زیر اِعمال خواهیم کرد:

>>> list1.sort()
>>> list1
['b', 'f', 'g', 'n', 'r', 's']

همان‌طور که مشاهده می‌کنید، فانکشن ()sort را روی آبجکت list1 فراخوانی کرده‌ایم که بدین ترتیب محتوای list1 بر اساس حروف الفبای انگلیسی مرتب شده و در معرض دیدمان قرار گرفته است اما در ادامه مثالی دیگر را به منظور آشنایی بیشتر با نحوۀ عملکرد فانکشن ()sort مورد بررسی قرار می‌دهیم:

>>> list2 = ['eat', 'ate', 'tea', 'sea', 'ease', 'see']
>>> list2.sort()
>>> list2
['ate', 'ease', 'eat', 'sea', 'see', 'tea']

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

علاوه بر این، فانکشن ()sort قابلیت اِعمال روی لیست‌هایی با آیتم‌های داخلی از نوع دادۀ عددی را دارا است؛ به عبارت دیگر، امکان مرتب‌سازی لیست‌هایی متشکل از یکسری آیتم با نوع دادۀ عددی نیز با به‌کارگیری فانکشن ()sort فراهم است که برای مثال‌ می‌توان کد زیر را مد نظر قرار داد:

>>> list3 = [43, 65, 20, 1, 79, 0.23, 102, 4]
>>> list3.sort()
>>> list3
[0.23, 1, 4, 20, 43, 65, 79, 102]

در مثال فوق، ابتدا به ساکن آبجکتی از جنس لیست تحت عنوان list3 تعریف کرده‌ایم که آیتم‌های تشکیل‌دهندۀ آن دیتا تایپ عددی دارند و در ادامه فانکشن ()sort را روی آبجکت مذکور فراخوانی کرده‌ایم که پس از اِعمال این فانکشن روی list3 محتوای آن از کوچک‌ترین عدد به بزرگ‌ترین مقدار مرتب شده است.

لازم به یادآوری است که زبان برنامه‌نویسی پایتون امکان مرتب کردن محتوای لیست را به صورت معکوس نیز فراهم کرده است که این موضوع با پیاده‌سازی دو روش متفاوت امکان‌پذیر می‌باشد که در ادامه به تشریح نحوۀ عملکرد هر یک می‌پردازیم.

در روش اول ابتدا لیست مد نظر را با به‌کارگیری فانکشن ()sort مرتب کرده و در ادامه فانکشن ()reverse را روی آن اِعمال می‌کنیم تا آیتم‌هایش بر اساس ترتیب معکوس در لیست مذکور قرار بگیرند. برای درک بهتر این موضوع، کد زیر را مد نظر قرار می‌دهیم:

>>> list3
[0.23, 1, 4, 20, 43, 65, 79, 102]
>>> list3.reverse()
>>> list3
[102, 79, 65, 43, 20, 4, 1, 0.23]

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

توجه داشته باشیم که فانکشن ()reverse صرفاً ترتیب قرارگیری اعضای لیست را معکوس می‌کند؛ بدین معنی که آیتم‌های آن را به ترتیب از انتهای لیست به ابتدا می‌چیند و از همین روی چنانچه قبل از مرتب‌سازی لیست یا به عبارتی پیش از اِعمال فانکشن ()sort روی آبجکت مد نظر فانکشن ()reverse را روی آن فراخوانی کنیم، خروجی حاصل مرتب نبوده و صرفاً اعضای آن از آخر به اول کنار هم قرار می‌گیرند. برای نمونه، آبجکت list3 از مثال قبل را پیش از اِعمال فانکشن ()sort روی آن مورد بررسی قرار می‌دهیم:

>>> list3 = [43, 65, 20, 1, 79, 0.23, 102, 4]
>>> list3.reverse()
>>> list3
[4, 102, 0.23, 79, 1, 20, 65, 43]

در حقیقت، لیستی داریم که فانکشن ()sort روی آن اِعمال نشده است و از همین روی با فراخوانی فانکشن ()reverse روی آبجکت مذکور صرفاً آیتم‌های داخل آن از انتها به ابتدا کنار هم قرار گرفته و هیچ ترتیب صعودی یا نزولی مشخصی ندارند.

روش دوم به منظور مرتب‌سازی معکوس اعضای لیست بدین ترتیب است که فانکشن ()sort را روی آبجکت مد نظر با یک آرگومان ورودی به صورت reverse = True فراخوانی کنیم که برای بررسی نحوۀ عملکرد آن کدی مانند زیر خواهیم داشت:

>>> list1 = ['s', 'r', 'f', 'g', 'n', 'b']
>>> list1.sort(reverse = True)
>>> list1
['s', 'r', 'n', 'g', 'f', 'b']

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

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

بر اساس آنچه که در نکتۀ فوق بیان شد، چنانچه بخواهیم یک کپی از لیست اصلی ایجاد کرده و تغییرات مد نظر را روی لیست حاصل اِعمال کنیم، کدی مانند زیر خواهیم داشت:

>>> originalList = ["Narges", "Reza", "Saeed", "Puya", "Marjan", "Saeedeh"]
>>> newList = originalList[:]
>>> newList.sort()
>>> originalList
['Narges', 'Reza', 'Saeed', 'Puya', 'Marjan', 'Saeedeh']
>>> newList
['Marjan', 'Narges', 'Puya', 'Reza', 'Saeed', 'Saeedeh']

در ابتدا لیستی تحت عنوان originalList متشکل از چند استرینگ ایجاد کرده‌ایم و متغیری به نام newList تعریف کرده و یک کپی از لیست originalList در آن ایجاد می‌کنیم که اکنون محتوای لیست originalList در آبجکت newList کپی شده است.

همان‌طور که در آموزش‌های گذشته اشاره کردیم، برای دسترسی به هر یک از آیتم‌های لیست می‌توان از دستوری با الگوی [listName[i : j استفاده کرد که بدین ترتیب به آیتم‌های مد نظر از اندیس i تا j دسترسی می‌یابیم. حال اگر بخواهیم به تمامی آیتم‌های یک لیست دسترسی داشته باشیم، اندیس‌های i و j را از الگوی فوق حذف کرده و الگویی به صورت [:]listName داریم که از همین روی در مثال فوق الگوی مذکور را به منظور دسترسی به تمامی محتوای originalList به کار گرفته و نتیجه را در متغیر newList کپی کرده‌ایم.

حال سؤالی که مطرح می‌شود این است که «چرا به جای استفاده از الگوی فوق دستوری همچون newList = originalList به کار نگرفته‌ایم؟» که در پاسخ به این سؤال می‌توان گفت که نام متغیرها مانند برچسبی است که به یک آبجکت منتسب می‌شود و از همین روی دستور newList = originalList به معنی انتساب برچسبی یکسان به دو آبجکت متفاوت است که در این صورت تمامی تغییرات اِعمال‌شده در یکی از لیست‌ها منجر به تغییر محتوای هر دو لیست ارجاع داده‌شده به آن نمی‌شود اما این در حالی است که به‌کارگیری علائم [:] در ادامۀ شناسۀ آبجکت originalList و انتساب آن به متغیر newList به معنای ایجاد شیئی جدید است که محتوای لیست اولیه را کپی کرده و آن را به متغیر newList ارجاع می‌دهد که در چنین شرایطی متغیر originalList همچنان به همان لیست اولیه منتسب بوده و بدین ترتیب دو متغیر ایجاد می‌شود که به آبجکت‌هایی متفاوت ارجاع می‌دهند و اِعمال تغییر در یکی از آن‌ها منجر به ایجاد تغییر در آبجکت دیگر نخواهد شد.

در واقع، همان‌طور که در کد فوق می‌بینید، اِعمال فانکشن ()sort روی آبجکت newList منجر به ریترن شدن لیستی مرتب در خروجی شده اما این در حالی است که لیست منتسب به آبجکت originalList بدون تغییر باقی مانده است.

همچنین روش دیگری در زبان برنامه‌نویسی پایتون وجود دارد تا بدون اِعمال تغییر روی لیست اصلی یک کپی از آن ایجاد کرده و اعضای لیست حاصل را مرتب کرد که برای این منظور فانکشن ()sorted را مورد استفاده قرار می‌دهیم. در حقیقت، فانکشن ()sorted بدین صورت عمل می‌کند که یک آرگومان ورودی از جنس لیست گرفته و در ادامه یک کپی از آن در قالب آبجکت جدیدی از جنس لیست ایجاد کرده و در ادامه آن را مرتب می‌کند که به عنوان یک مثال از کاربرد این فانکشن داریم:

>>> original = [5, 2, 3, 1, 4]
>>> newer = sorted(original)
>>> original
[5, 2, 3, 1, 4]
>>> newer
[1, 2, 3, 4, 5]

در کد فوق لیستی متشکل از مقادیر عددی تحت عنوان original ایجاد کرده و آن را به عنوان ورودی به فانکشن ()sorted داده‌ایم و در ادامه خروجی حاصل از آن را به متغیری تحت عنوان newer منتسب کرده‌ایم که بدین ترتیب فانکشن ()sorted ابتدا یک کپی از لیست اولیه گرفته و در ادامه آیتم‌های آن را مرتب می‌کند که در نهایت لیست جدید به متغیر newer ارجاع داده می‌شود و همان‌طور که ملاحظه می‌کنید، محتوای لیست original تغییری نکرده است.

در پایان توجه داشته باشیم که فانشکن ()sort و دیگر فانکشن‌های معرفی‌شده در این مقاله همچون ()reverse و ()sorted را در صورتی می‌توان روی محتوای آبجکت‌هایی از جنس لیست اِعمال کرد که تمامی آیتم‌های لیست دیتا تایپی یکسان داشته باشند که به عنوان یک نمونه می‌توان کد زیر را در این ارتباط مد نظر قرار داد:

>>> list4 = ['h', 't', 'm', 'p', 10, 8, 32]
>>> list4.sort()
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in 
    list4.sort()
TypeError: unorderable types: int() < str()

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


لیست نظرات
کاربر میهمان
دیدگاه شما چیست؟
کاربر میهمان
فردی
فردی
۱۳۹۵/۰۷/۲۴
سلام. آیا در مثال بالا میتونانیم بجای ListName[:] از دستور copy() استفاده کنیم؟