مرتب سازی پایتون

ساده ترین راه برای مرتب سازی تابع sorted(list) است که یک لیست را می گیرد و یک لیست جدید با آن عناصر را به ترتیب مرتب شده برمی گرداند. لیست اصلی تغییر نکرده است.

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

معمولاً ارسال یک لیست به تابع sorted() است، اما در واقع می‌تواند هر نوع مجموعه تکرارپذیر را به عنوان ورودی بگیرد. متد ()list.sort قدیمی جایگزینی است که در زیر توضیح داده شده است. استفاده از تابع sorted() در مقایسه با sort() راحت تر به نظر می رسد، بنابراین توصیه می کنم از sorted() استفاده کنید.

تابع sorted() را می توان از طریق آرگومان های اختیاری سفارشی کرد. آرگومان اختیاری sorted() reverse=True، به عنوان مثال sorted(list, reverse=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" را مشخص می‌کند که هر عنصر را قبل از مقایسه تبدیل می‌کند. تابع کلید 1 مقدار را دریافت می کند و 1 مقدار را برمی گرداند و مقدار "پراکسی" بازگشتی برای مقایسه های درون مرتب سازی استفاده می شود.

به عنوان مثال با لیستی از رشته ها، تعیین 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']

برای مرتب‌سازی پیچیده‌تر مانند مرتب‌سازی بر اساس نام خانوادگی و سپس با نام، می‌توانید از توابع آیتم‌گتر یا 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() باید در یک لیست فراخوانی شود. بر روی هیچ مجموعه ای قابل شمارش کار نمی کند (اما تابع sorted() بالا روی هر چیزی کار می کند). متد sort () قبل از تابع sorted() است، بنابراین احتمالاً آن را در کدهای قدیمی‌تر خواهید دید. متد sort() نیازی به ایجاد یک لیست جدید ندارد، بنابراین در صورتی که عناصر مرتب‌سازی از قبل در یک لیست باشند، می‌تواند کمی سریع‌تر باشد.

تاپل ها

تاپل یک گروه بندی با اندازه ثابت از عناصر است، مانند مختصات (x، y). تاپل ها مانند لیست ها هستند، با این تفاوت که تغییر ناپذیر هستند و اندازه آنها تغییر نمی کند (تاپل ها کاملاً تغییر ناپذیر نیستند زیرا یکی از عناصر موجود می تواند تغییر پذیر باشد). تاپل ها نوعی نقش "ساختار" را در پایتون ایفا می کنند - راهی مناسب برای انتقال مقادیر کمی منطقی و با اندازه ثابت. تابعی که باید چندین مقدار را برگرداند، می‌تواند فقط چند عدد از مقادیر را برگرداند. به عنوان مثال، اگر من بخواهم فهرستی از مختصات 3 بعدی داشته باشم، نمایش پایتون طبیعی فهرستی از تاپل ها خواهد بود، که در آن هر تاپل اندازه 3 است و یک گروه (x، y، z) را در خود جای داده است.

برای ایجاد یک تاپل، کافیست مقادیر درون پرانتز را که با کاما از هم جدا شده اند فهرست کنید. تاپل "خالی" فقط یک جفت پرانتز خالی است. دسترسی به عناصر در یک تاپل درست مانند یک لیست است -- 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، عنصر lone باید با کاما دنبال شود.

  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 شبیه یک حلقه for معمولی است، اما بدون دو نقطه (:). expr در سمت چپ آن یک بار برای هر عنصر ارزیابی می شود تا مقادیر لیست جدید را بدهد. در اینجا یک مثال با رشته ها وجود دارد که در آن هر رشته با حروف بزرگ با "!!!" تغییر می کند. ضمیمه شده:

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

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

برای محدود کردن نتیجه، می‌توانید یک تست if را در سمت راست حلقه for اضافه کنید. آزمون 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 امتحان کنید که از مرتب‌سازی و تاپل (در تمرین‌های پایه ) استفاده می‌کنند.