Mundarija (23)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. sort() vs sorted()
- 2.2. key funksiyasi
- 2.3. Barqarorlik (stability)
- 2.4. reverse parametri
- 2.5. Nima saralanadi — solishtirish qoidalari
- 2.6. Timsort — Python algoritmi
- 2.7. functools.cmp_to_key
- 2.8. Qisman saralash — heapq
- 2.9. Sinf obyektlarini saralash
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — key funksiyasi to'liq
- Misol 2 — Barqarorlik
- Misol 3 — Tuzoqlar
- Misol 4 — Amaliy: hisobot generatori
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
6.3-dars: Ro'yxatni saralash — sort va sorted
6-QISM — MA'LUMOT TUZILMALARI · 3-dars
1. Kirish va motivatsiya
Saralash — dasturlashdagi eng ko'p ishlatiladigan amallardan biri. Pythonda u juda oson ko'rinadi:
royxat = [3, 1, 2]
royxat.sort()
print(royxat) # [1, 2, 3]Lekin haqiqiy vazifalar oddiy emas:
xodimlar = [
{"ism": "Aziz", "yosh": 30, "maosh": 5_000_000},
{"ism": "Bobur", "yosh": 25, "maosh": 7_000_000},
{"ism": "Aziza", "yosh": 30, "maosh": 6_000_000},
]
# Yosh bo'yicha saralang. Yoshlar teng bo'lsa — maosh bo'yicha kamayish tartibida.Yoki:
sozlar = ["Olma", "anor", "Behi"]
sozlar.sort()
print(sozlar) # ['Behi', 'Olma', 'anor'] ← nega?!Yoki:
royxat = [1, "2", 3]
royxat.sort() # ❌ TypeErrorBu darsda:
sort()vssorted()— qachon qaysi birikeyfunksiyasi — saralashning yuragi- Barqarorlik (stability) va ko'p mezonli saralash
reverseva teskari tartib nozikliklari- Timsort — Python algoritmi
functools.cmp_to_key,operator.itemgetter
2. Nazariya — chuqur tushuntirish
2.1. sort() vs sorted()
royxat.sort() |
sorted(iterable) |
|
|---|---|---|
| Nima | list metodi |
Ichki funksiya |
| Ishlaydi | Faqat list bilan |
Har qanday iterable |
| Natija | None |
Yangi list |
| Asl | O'zgaradi | O'zgarmaydi |
| Xotira | O(n) vaqtincha | O(n) yangi |
r = [3, 1, 2]
r.sort() # joyida
print(r) # [1, 2, 3]
r = [3, 1, 2]
yangi = sorted(r) # yangi ro'yxat
print(r, yangi) # [3, 1, 2] [1, 2, 3]sorted() har qanday iterable bilan:
sorted("cba") # ['a', 'b', 'c'] ← LIST qaytaradi
sorted({3, 1, 2}) # [1, 2, 3]
sorted({"b": 2, "a": 1}) # ['a', 'b'] ← kalitlar
sorted({"b": 2, "a": 1}.items()) # [('a', 1), ('b', 2)]
sorted(range(5, 0, -1)) # [1, 2, 3, 4, 5]
sorted(x for x in [3, 1, 2]) # [1, 2, 3] ← generator sorted() doim list qaytaradi — hatto satr yoki to'plamdan ham.
Qachon qaysi biri:
# Asl kerak emas, ro'yxat — sort() (biroz tejamli)
royxat.sort()
# Asl saqlanishi kerak — sorted()
saralangan = sorted(royxat)
# Ro'yxat emas — sorted()
saralangan = sorted(toplam)
# Funksiya argumentini o'zgartirmaslik kerak — sorted()
def eng_kattalari(malumot, n=3):
return sorted(malumot, reverse=True)[:n] # ✅ malumot o'zgarmaydi2.2. key funksiyasi
key — har bir element uchun chaqiriladigan funksiya. Uning natijasi bo'yicha saralanadi.
sozlar = ["shaftoli", "olma", "banan"]
sorted(sozlar) # ['banan', 'olma', 'shaftoli'] — alifbo
sorted(sozlar, key=len) # ['olma', 'banan', 'shaftoli'] — uzunlikQanday ishlaydi:
sozlar: ["shaftoli", "olma", "banan"]
key=len: [ 8, 4, 5 ] ← key hisoblanadi
saralash: [ 4, 5, 8 ] ← kalitlar saralanadi
natija: ["olma", "banan", "shaftoli"] ← elementlar ko'chiriladiMuhim: key har bir element uchun faqat bir marta chaqiriladi (decorate-sort-undecorate naqshi). Bu — samaradorlik uchun.
def qimmat_kalit(x):
print(f" key({x}) chaqirildi")
return len(x)
sorted(["aa", "b", "ccc"], key=qimmat_kalit) key(aa) chaqirildi
key(b) chaqirildi
key(ccc) chaqirildi3 element → 3 chaqiruv. Solishtirishlar esa ~n log n ta bo'lardi.
Keng tarqalgan key funksiyalari:
# Uzunlik
sorted(sozlar, key=len)
# Registrsiz (⚠️ casefold, lower emas — 4.4-dars)
sorted(sozlar, key=str.casefold)
# Lug'at maydoni
sorted(xodimlar, key=lambda x: x["yosh"])
# Obyekt atributi
sorted(xodimlar, key=lambda x: x.yosh)
# Absolyut qiymat
sorted([-3, 1, -2], key=abs) # [1, -2, -3]
# Oxirgi belgi
sorted(sozlar, key=lambda s: s[-1])
# Bir nechta mezon (tuple!)
sorted(xodimlar, key=lambda x: (x["yosh"], x["ism"]))operator moduli — tezroq:
from operator import itemgetter, attrgetter, methodcaller
sorted(xodimlar, key=itemgetter("yosh")) # lug'at/tuple
sorted(xodimlar, key=itemgetter("yosh", "ism")) # ko'p mezon
sorted(juftliklar, key=itemgetter(1)) # tuple 1-elementi
sorted(obyektlar, key=attrgetter("yosh")) # atribut
sorted(sozlar, key=methodcaller("count", "a")) # metod chaqirishitemgetter — C da yozilgan, lambda dan ~20-30% tezroq.
2.3. Barqarorlik (stability)
Python saralashi barqaror — teng kalitli elementlar asl tartibini saqlaydi.
malumot = [("a", 2), ("b", 1), ("c", 2), ("d", 1)]
sorted(malumot, key=itemgetter(1))
# [('b', 1), ('d', 1), ('a', 2), ('c', 2)]
# ↑ ↑ ↑ ↑
# b, d asl tartibda; a, c asl tartibdaBu — kafolatlangan xususiyat (til spetsifikatsiyasida yozilgan), tasodif emas.
Nega muhim — ko'p mezonli saralash:
Barqarorlik tufayli ketma-ket saralash ishlaydi:
# Yosh bo'yicha, teng bo'lsa — ism bo'yicha
# Usul 1: tuple kalit (bir o'tish) ✅
sorted(xodimlar, key=lambda x: (x["yosh"], x["ism"]))
# Usul 2: ketma-ket saralash (barqarorlik tufayli)
xodimlar.sort(key=itemgetter("ism")) # AVVAL ikkilamchi
xodimlar.sort(key=itemgetter("yosh")) # KEYIN asosiyTartib teskari! Ikkinchi usulda eng muhim mezon oxirida saralanadi.
Qachon 2-usul kerak:
Turli yo'nalishlarda saralash kerak bo'lganda:
# Yosh o'sish, maosh kamayish tartibida
# ❌ tuple bilan qiyin (turli yo'nalish)
sorted(xodimlar, key=lambda x: (x["yosh"], ???))
# ✅ ketma-ket
xodimlar.sort(key=itemgetter("maosh"), reverse=True) # ikkilamchi
xodimlar.sort(key=itemgetter("yosh")) # asosiy
# ✅ Yoki sonlar uchun minus
sorted(xodimlar, key=lambda x: (x["yosh"], -x["maosh"]))Minus faqat sonlar bilan ishlaydi:
sorted(x, key=lambda v: (-v["yosh"], v["ism"])) # ✅ son
sorted(x, key=lambda v: (v["yosh"], -v["ism"])) # ❌ TypeError — satrSatr uchun teskari yo'nalish — faqat ketma-ket saralash.
2.4. reverse parametri
sorted([3, 1, 2], reverse=True) # [3, 2, 1]
royxat.sort(reverse=True) reverse=True ≠ sorted(...)[::-1] — barqarorlik boshqacha:
malumot = [("a", 1), ("b", 1)]
sorted(malumot, key=itemgetter(1), reverse=True)
# [('a', 1), ('b', 1)] ← asl tartib SAQLANADI
sorted(malumot, key=itemgetter(1))[::-1]
# [('b', 1), ('a', 1)] ← tartib TESKARI!reverse=True barqarorlikni buzmaydi — u faqat solishtirish yo'nalishini o'zgartiradi. [::-1] esa hamma narsani teskari qiladi.
Shuning uchun doim reverse=True ishlating.
2.5. Nima saralanadi — solishtirish qoidalari
Saralash < operatoriga tayanadi. Element < ni qo'llab-quvvatlashi kerak.
Sonlar:
sorted([3, 1.5, 2]) # [1.5, 2, 3] — int va float aralash ✅Satrlar — kod nuqtasi bo'yicha (4.8-dars):
sorted(["Olma", "anor", "Behi"])
# ['Behi', 'Olma', 'anor']
# B=66 O=79 a=97 Katta harflar oldin keladi — chunki ASCII da A(65) < a(97).
sorted(["Olma", "anor", "Behi"], key=str.casefold)
# ['anor', 'Behi', 'Olma'] ✅O'zbek harflari:
sorted(["shaftoli", "olma", "o'rik", "anor"])
# ['anor', 'olma', "o'rik", 'shaftoli']
# ⚠️ Lekin: o' va oʻ turlicha saralanadi (4.8-dars)
sorted(["oʻrik", "o'rik", "olma"])
# ['olma', "o'rik", 'oʻrik'] — U+0027 (39) < U+02BB (699)Yechim — normalizatsiya:
def uzbek_kalit(s: str) -> str:
return s.replace("ʻ", "'").replace("'", "'").casefold()
sorted(sozlar, key=uzbek_kalit)Tuple va list — leksikografik:
sorted([(1, "b"), (1, "a"), (0, "z")])
# [(0, 'z'), (1, 'a'), (1, 'b')]Avval 0-element, teng bo'lsa 1-element, ...
Turli tur — TypeError:
sorted([1, "2", 3])
# ❌ TypeError: '<' not supported between instances of 'str' and 'int'
sorted([1, None])
# ❌ TypeError
sorted([1, 2.5, True])
# ✅ [1, True, 2.5] — bool int ning qism turi; True == 1, saralash barqaror
# bo'lgani uchun teng elementlar ASL tartibda qoladiBu — Python 3 o'zgarishi. Python 2 da har qanday tur solishtirilardi (natija ma'nosiz bo'lsa ham). Python 3 bu "jimgina noto'g'ri" xatti-harakatni yo'q qildi.
None bilan saralash:
malumot = [3, None, 1, None, 2]
# ❌ TypeError
sorted(malumot)
# ✅ None ni oxiriga
sorted(malumot, key=lambda x: (x is None, x))
# ✅ None ni boshiga
sorted(malumot, key=lambda x: (x is not None, x))
# ✅ None ni sukut qiymat bilan
sorted(malumot, key=lambda x: x if x is not None else 0)(x is None, x) — hiyla: False < True, shuning uchun None bo'lmaganlar oldin.
Lekin bu None bo'lganda ikkinchi element None bo'ladi — teng True lar orasida solishtirish kerak bo'lmasa ishlaydi (barqarorlik tufayli teng kalitlar solishtirilmaydi).
Xavfsizroq:
sorted(malumot, key=lambda x: (x is None, x if x is not None else 0))2.6. Timsort — Python algoritmi
Python Timsort ishlatadi — Tim Peters (Zen muallifi) 2002 yilda yaratgan.
Xususiyatlari:
| Turi | Gibrid: merge sort + insertion sort |
| Barqaror | Ha |
| Eng yomon | O(n log n) |
| Eng yaxshi | O(n) — allaqachon saralangan |
| Xotira | O(n) |
| Adaptiv | Qisman saralangan ma'lumotda tez |
Asosiy g'oya: haqiqiy ma'lumot ko'pincha qisman saralangan bo'ladi. Timsort tabiiy o'sish/kamayish ketma-ketliklarini (run) topadi va ularni birlashtiradi.
# Deyarli saralangan — juda tez
malumot = list(range(1_000_000))
malumot[500_000] = -1
malumot.sort() # ~O(n)
# Tasodifiy — O(n log n)
random.shuffle(malumot)
malumot.sort()Timsort shunchalik yaxshiki, Java, Android, Swift, Rust ham uni qabul qilgan.
Amaliy xulosa: Python saralashi juda optimallashtirilgan. O'z algoritmingizni yozmang.
2.7. functools.cmp_to_key
Python 2 da sort(cmp=...) bor edi — ikkita elementni solishtiruvchi funksiya. Python 3 da olib tashlangan.
Agar eski solishtirish mantig'i kerak bo'lsa:
from functools import cmp_to_key
def solishtir(a, b):
"""Manfiy: a < b, 0: teng, musbat: a > b."""
if len(a) != len(b):
return len(a) - len(b)
return (a > b) - (a < b)
sorted(sozlar, key=cmp_to_key(solishtir)) cmp_to_key sekin — har bir solishtirish uchun obyekt yaratadi. Deyarli har doim key bilan yozish mumkin:
# cmp o'rniga
sorted(sozlar, key=lambda s: (len(s), s)) # ✅ tezroqcmp_to_key haqiqatan kerak bo'lgan holat: solishtirish tranzitiv bo'lmagan yoki kalit sifatida ifodalab bo'lmaydigan bo'lsa (juda kam uchraydi).
2.8. Qisman saralash — heapq
Faqat eng katta/kichik n ta kerak bo'lsa, to'liq saralash isrof:
import heapq
# ❌ O(n log n)
eng_kattalar = sorted(malumot, reverse=True)[:10]
# ✅ O(n log k)
eng_kattalar = heapq.nlargest(10, malumot)
eng_kichiklar = heapq.nsmallest(10, malumot)
# key bilan
heapq.nlargest(3, xodimlar, key=itemgetter("maosh"))Qachon foydali:
| n (jami) | k (kerak) | Tavsiya |
|---|---|---|
| Har qanday | k = 1 | max() / min() |
| Katta | k << n | heapq.nlargest |
| Har qanday | k ≈ n | sorted() |
k = 1 bo'lsa max() eng tez.
2.9. Sinf obyektlarini saralash
8-qismda batafsil, hozircha asosiy:
from dataclasses import dataclass, field
@dataclass(order=True) # ⭐ order=True — solishtirish metodlari
class Xodim:
maosh: int
ism: str
xodimlar = [Xodim(5000, "Aziz"), Xodim(3000, "Bobur")]
xodimlar.sort() # ✅ maosh, keyin ism bo'yicha order=True maydon tartibiga qarab solishtiradi. Boshqacha kerak bo'lsa:
@dataclass(order=True)
class Xodim:
saralash_kaliti: int = field(init=False, repr=False)
ism: str
maosh: int
def __post_init__(self):
self.saralash_kaliti = -self.maosh # kamayish tartibidaYoki oddiyroq — key ishlating:
xodimlar.sort(key=attrgetter("maosh"), reverse=True)3. Tez ma'lumotnoma
sort vs sorted
royxat.sort() joyida, None, faqat list
sorted(iterable) yangi list, har qanday iterable
royxat.sort(key=..., reverse=...)
sorted(it, key=..., reverse=...)key funksiyalari
key=len uzunlik
key=str.casefold registrsiz ⭐
key=abs absolyut qiymat
key=lambda x: x["yosh"] lug'at maydoni
key=itemgetter("yosh") tezroq ⭐
key=attrgetter("yosh") atribut
key=lambda x: (a, b) ko'p mezonBarqarorlik
Teng kalitlar asl tartibda qoladi — KAFOLATLANGAN
Ko'p mezon, turli yo'nalish:
r.sort(key=ikkilamchi, reverse=True) # AVVAL ikkilamchi
r.sort(key=asosiy) # KEYIN asosiy
reverse=True ✅ barqarorlikni saqlaydi
sorted(...)[::-1] ❌ tartibni buzadiTuzoqlar
sorted(["Olma","anor"]) ['Olma','anor'] — katta harf oldin
sorted([1,"2"]) ❌ TypeError
sorted([1,None]) ❌ TypeError
→ key=lambda x: (x is None, x)
saralangan = r.sort() ❌ NoneTezroq muqobillar
max(r) / min(r) k=1
heapq.nlargest(k, r) k << n
sorted(r)[:k] k ≈ n4. Batafsil misollar
Misol 1 — key funksiyasi to'liq
"""key parametrining barcha shakllari."""
from operator import itemgetter, attrgetter, methodcaller
from dataclasses import dataclass
print("=== 1. Oddiy key funksiyalari ===")
SOZLAR = ["shaftoli", "Olma", "banan", "anor", "uzum"]
print(f" Asl: {SOZLAR}\n")
VARIANTLAR = [
("key yo'q", None),
("key=len", len),
("key=str.casefold", str.casefold),
("key=str.lower", str.lower),
("oxirgi belgi", lambda s: s[-1]),
("unli harflar soni", lambda s: sum(c in "aeiou" for c in s.lower())),
("(uzunlik, alifbo)", lambda s: (len(s), s.casefold())),
]
for nom, kalit in VARIANTLAR:
natija = sorted(SOZLAR) if kalit is None else sorted(SOZLAR, key=kalit)
print(f" {nom:<20} {natija}")
print("\n\n=== 2. key faqat BIR MARTA chaqiriladi ===")
chaqiruvlar = []
def kuzatuvchi_kalit(x):
chaqiruvlar.append(x)
return len(x)
sorted(SOZLAR, key=kuzatuvchi_kalit)
print(f" Elementlar soni: {len(SOZLAR)}")
print(f" key chaqiruvlari: {len(chaqiruvlar)}")
print(f" Tartib: {chaqiruvlar}")
print(f"\n ⭐ Har element uchun bir marta — decorate-sort-undecorate")
print("\n\n=== 3. Lug'atlar bilan ===")
XODIMLAR = [
{"ism": "Aziz", "yosh": 30, "maosh": 5_000_000, "bolim": "IT"},
{"ism": "Bobur", "yosh": 25, "maosh": 7_000_000, "bolim": "Moliya"},
{"ism": "Aziza", "yosh": 30, "maosh": 6_000_000, "bolim": "IT"},
{"ism": "Dilnoza", "yosh": 25, "maosh": 5_000_000, "bolim": "HR"},
]
def chiqar(xodimlar, sarlavha):
print(f"\n {sarlavha}")
print(f" {'Ism':<10} {'Yosh':>5} {'Maosh':>12} Bo'lim")
print(" " + "─" * 42)
for x in xodimlar:
print(f" {x['ism']:<10} {x['yosh']:>5} {x['maosh']:>12,} {x['bolim']}")
chiqar(XODIMLAR, "Asl:")
chiqar(sorted(XODIMLAR, key=lambda x: x["yosh"]), "key=lambda x: x['yosh']:")
chiqar(sorted(XODIMLAR, key=itemgetter("maosh"), reverse=True),
"itemgetter('maosh'), reverse=True:")
chiqar(sorted(XODIMLAR, key=itemgetter("yosh", "ism")),
"itemgetter('yosh', 'ism') — ko'p mezon:")
print("\n\n=== 4. Turli yo'nalishlar ===")
print("\n Vazifa: yosh O'SISH, maosh KAMAYISH tartibida\n")
# Usul 1: minus (faqat sonlar)
u1 = sorted(XODIMLAR, key=lambda x: (x["yosh"], -x["maosh"]))
chiqar(u1, "Usul 1: key=(yosh, -maosh)")
# Usul 2: ketma-ket saralash (barqarorlik)
u2 = XODIMLAR.copy()
u2.sort(key=itemgetter("maosh"), reverse=True) # AVVAL ikkilamchi
u2.sort(key=itemgetter("yosh")) # KEYIN asosiy
chiqar(u2, "Usul 2: ketma-ket (ikkilamchi → asosiy)")
print(f"\n Bir xilmi: {u1 == u2}")
print("\n ⚠️ Satr uchun minus ishlamaydi:")
try:
sorted(XODIMLAR, key=lambda x: (x["yosh"], -x["ism"]))
except TypeError as x:
print(f" key=(yosh, -ism) → TypeError: {x}")
print(" → Satrni teskari saralash uchun ketma-ket usul kerak")
print("\n\n=== 5. operator moduli ===")
import time
N = 200_000
MALUMOT = [{"a": i % 1000, "b": i} for i in range(N)]
USULLAR = [
("lambda x: x['a']", lambda x: x["a"]),
("itemgetter('a')", itemgetter("a")),
]
print(f" {N:,} lug'atni saralash:\n")
natijalar = []
for nom, kalit in USULLAR:
nusxa = MALUMOT.copy()
boshlandi = time.perf_counter()
nusxa.sort(key=kalit)
natijalar.append((nom, time.perf_counter() - boshlandi))
eng_tez = min(v for _, v in natijalar)
for nom, vaqt in natijalar:
print(f" {nom:<24} {vaqt * 1000:>7.1f} ms {vaqt / eng_tez:>5.2f}x")
print("\n\n=== 6. attrgetter va methodcaller ===")
@dataclass
class Mahsulot:
nom: str
narx: int
ombor: int
MAHSULOTLAR = [
Mahsulot("Non", 5_000, 100),
Mahsulot("Sut", 12_000, 40),
Mahsulot("Yog'", 45_000, 15),
]
print(" attrgetter('narx'):")
for m in sorted(MAHSULOTLAR, key=attrgetter("narx")):
print(f" {m.nom:<6} {m.narx:>8,} so'm ({m.ombor} dona)")
print("\n attrgetter('ombor', 'nom') — ko'p atribut:")
for m in sorted(MAHSULOTLAR, key=attrgetter("ombor", "nom")):
print(f" {m.nom:<6} {m.ombor:>4} dona")
print("\n methodcaller('count', 'o'):")
for s in sorted(["olmalar", "non", "shokolad"], key=methodcaller("count", "o")):
print(f" {s:<10} 'o' soni: {s.count('o')}")Natijaning muhim qismi:
=== 1. Oddiy key funksiyalari ===
Asl: ['shaftoli', 'Olma', 'banan', 'anor', 'uzum']
key yo'q ['Olma', 'anor', 'banan', 'shaftoli', 'uzum']
key=len ['Olma', 'anor', 'uzum', 'banan', 'shaftoli']
key=str.casefold ['anor', 'banan', 'Olma', 'shaftoli', 'uzum']
=== 2. key faqat BIR MARTA chaqiriladi ===
Elementlar soni: 5
key chaqiruvlari: 5
⭐ Har element uchun bir marta — decorate-sort-undecorate
=== 5. operator moduli ===
200,000 lug'atni saralash:
lambda x: x['a'] 84.3 ms 1.31x
itemgetter('a') 64.2 ms 1.00xNima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 2 — Barqarorlik
"""Barqarorlik nima va nega muhim."""
from operator import itemgetter
print("=== 1. Barqarorlik namoyishi ===")
MALUMOT = [
("Aziz", "IT"),
("Bobur", "HR"),
("Aziza", "IT"),
("Dilnoza", "HR"),
("Eldor", "IT"),
]
print(" Asl tartib:")
for ism, bolim in MALUMOT:
print(f" {ism:<10} {bolim}")
print("\n Bo'lim bo'yicha saralangandan keyin:")
for ism, bolim in sorted(MALUMOT, key=itemgetter(1)):
print(f" {ism:<10} {bolim}")
print("""
⭐ HR ichida: Bobur, Dilnoza — asl tartibda
IT ichida: Aziz, Aziza, Eldor — asl tartibda
Bu KAFOLATLANGAN, tasodif emas.
""")
print("\n=== 2. Ko'p mezon: ikki usul ===")
XODIMLAR = [
{"ism": "Aziz", "bolim": "IT", "maosh": 5_000_000},
{"ism": "Bobur", "bolim": "Moliya", "maosh": 7_000_000},
{"ism": "Aziza", "bolim": "IT", "maosh": 8_000_000},
{"ism": "Dilnoza", "bolim": "HR", "maosh": 5_000_000},
{"ism": "Eldor", "bolim": "IT", "maosh": 5_000_000},
{"ism": "Feruza", "bolim": "Moliya", "maosh": 9_000_000},
]
def chiqar(xodimlar, sarlavha):
print(f"\n {sarlavha}")
for x in xodimlar:
print(f" {x['bolim']:<8} {x['ism']:<10} {x['maosh']:>10,}")
print("\n Vazifa: bo'lim bo'yicha, ichida maosh KAMAYISH tartibida")
# Usul 1: tuple + minus
u1 = sorted(XODIMLAR, key=lambda x: (x["bolim"], -x["maosh"]))
chiqar(u1, "Usul 1: (bolim, -maosh)")
# Usul 2: ketma-ket
u2 = XODIMLAR.copy()
u2.sort(key=itemgetter("maosh"), reverse=True)
u2.sort(key=itemgetter("bolim"))
chiqar(u2, "Usul 2: ketma-ket")
print(f"\n Bir xilmi: {u1 == u2}")
print("""
⚠️ Ketma-ket usulda TARTIB TESKARI:
avval ENG KAM muhim mezon
oxirida ENG MUHIM mezon
""")
print("\n=== 3. reverse=True vs [::-1] ===")
MALUMOT2 = [("a", 1), ("b", 1), ("c", 2), ("d", 2)]
print(f" Asl: {MALUMOT2}\n")
r1 = sorted(MALUMOT2, key=itemgetter(1), reverse=True)
r2 = sorted(MALUMOT2, key=itemgetter(1))[::-1]
print(f" reverse=True: {r1}")
print(f" sorted(...)[::-1]: {r2}")
print(f" Bir xilmi: {r1 == r2}")
print("""
⭐ reverse=True — barqarorlikni SAQLAYDI:
teng kalitlar asl tartibda (a, b va c, d)
❌ [::-1] — HAMMASINI teskari qiladi:
teng kalitlar ham teskari (b, a va d, c)
→ Doim reverse=True ishlating
""")
print("\n=== 4. Barqarorlik amaliyotda: jadval ustunlari ===")
TALABALAR = [
{"ism": "Aziz", "guruh": "A", "ball": 85},
{"ism": "Bobur", "guruh": "B", "ball": 92},
{"ism": "Aziza", "guruh": "A", "ball": 92},
{"ism": "Dilnoza", "guruh": "B", "ball": 78},
{"ism": "Eldor", "guruh": "A", "ball": 85},
]
class Jadval:
"""Foydalanuvchi ustun sarlavhasini bosgandagi xatti-harakat."""
def __init__(self, qatorlar):
self.qatorlar = list(qatorlar)
self.tarix = []
def sarala(self, ustun, kamayish=False):
"""Barqarorlik tufayli oldingi saralash 'eslab qolinadi'."""
self.qatorlar.sort(key=itemgetter(ustun), reverse=kamayish)
self.tarix.append(f"{ustun}{'↓' if kamayish else '↑'}")
return self
def chiqar(self):
yol = " → ".join(self.tarix) or "(saralanmagan)"
print(f"\n Bosilgan ustunlar: {yol}")
print(f" {'Ism':<10} {'Guruh':<7} {'Ball':>5}")
print(" " + "─" * 24)
for q in self.qatorlar:
print(f" {q['ism']:<10} {q['guruh']:<7} {q['ball']:>5}")
j = Jadval(TALABALAR)
j.chiqar()
j.sarala("ball", kamayish=True).chiqar()
j.sarala("guruh").chiqar()
print("""
⭐ Foydalanuvchi 'ball' ni bosdi, keyin 'guruh' ni bosdi
→ guruh bo'yicha, ichida ball kamayish tartibida
Bu — barqarorlikning eng foydali qo'llanishi.
Hech qanday qo'shimcha kod kerak emas.
""")
print("\n=== 5. Barqarorlik va o'zgaruvchan kalitlar ===")
print(""" ⚠️ Saralash paytida ro'yxatni o'zgartirmang:""")
r = [3, 1, 2]
class Yomon:
def __init__(self, q, royxat):
self.q = q
self.royxat = royxat
def __lt__(self, boshqa):
self.royxat.append(99) # ⚠️ saralash paytida o'zgartirish
return self.q < boshqa.q
royxat = []
royxat.extend(Yomon(i, royxat) for i in [3, 1, 2])
try:
royxat.sort()
print(f" Natija uzunligi: {len(royxat)} (kutilgan 3)")
except ValueError as x:
print(f" ValueError: {x}")
print("""
Python saralash paytida ro'yxatni vaqtincha BO'SH qiladi —
bu o'zgartirishlarni aniqlash uchun.
Ba'zi holatlarda "list modified during sort" xatosi chiqadi.
""")Natijaning muhim qismi:
=== 3. reverse=True vs [::-1] ===
Asl: [('a', 1), ('b', 1), ('c', 2), ('d', 2)]
reverse=True: [('c', 2), ('d', 2), ('a', 1), ('b', 1)]
sorted(...)[::-1]: [('d', 2), ('c', 2), ('b', 1), ('a', 1)]
Bir xilmi: False
=== 4. Barqarorlik amaliyotda: jadval ustunlari ===
Bosilgan ustunlar: ball↓ → guruh↑
Ism Guruh Ball
────────────────────────
Aziza A 92
Aziz A 85
Eldor A 85
Bobur B 92
Dilnoza B 78Nima ko'rsatdi: 2.3, 2.4-bo'limlar.
Misol 3 — Tuzoqlar
"""Saralashdagi keng tarqalgan tuzoqlar."""
print("=== 1. Katta va kichik harflar ===")
SOZLAR = ["Olma", "anor", "Behi", "shaftoli", "Uzum"]
print(f" Asl: {SOZLAR}\n")
print(f" sorted(): {sorted(SOZLAR)}")
print(f" key=str.lower: {sorted(SOZLAR, key=str.lower)}")
print(f" key=str.casefold: {sorted(SOZLAR, key=str.casefold)}")
print("\n Nega? Kod nuqtalari:")
for s in ["Olma", "anor", "Behi"]:
print(f" {s:<10} birinchi belgi {s[0]!r} = {ord(s[0])}")
print("\n ⭐ Katta harflar (65-90) < kichik harflar (97-122)")
print("\n\n=== 2. O'zbek apostroflari ===")
APOSTROFLAR = ["oʻrik", "o'rik", "o'rik", "olma", "orzu"]
print(" Ro'yxat:")
for s in APOSTROFLAR:
kodlar = " ".join(f"U+{ord(c):04X}" for c in s)
print(f" {s:<8} {kodlar}")
print(f"\n sorted(): {sorted(APOSTROFLAR)}")
def uzbek_kalit(s: str) -> str:
"""Apostrof variantlarini birlashtirish."""
for x in "ʻʼ''`":
s = s.replace(x, "'")
return s.casefold()
print(f" uzbek_kalit: {sorted(APOSTROFLAR, key=uzbek_kalit)}")
print("\n ⭐ Apostrof variantlari turli kod nuqtalari — normalizatsiya kerak")
print("\n\n=== 3. Turli turlar ===")
SINOVLAR = [
("[3, 1, 2]", [3, 1, 2]),
("[3, 1.5, 2]", [3, 1.5, 2]),
("[1, True, 2.5]", [1, True, 2.5]),
("[1, '2', 3]", [1, "2", 3]),
("[1, None, 2]", [1, None, 2]),
("[[1], [2]]", [[1], [2]]),
("[(1,2), (1,1)]", [(1, 2), (1, 1)]),
("[{1}, {2}]", [{1}, {2}]),
]
for nom, malumot in SINOVLAR:
try:
natija = str(sorted(malumot))
except TypeError as x:
natija = f"❌ TypeError: {str(x)[:44]}"
print(f" {nom:<18} → {natija}")
print("\n ⚠️ {1} va {2} — to'plamlar qism-to'plam bo'yicha solishtiriladi")
print(" (qisman tartib — natija kutilmagan bo'lishi mumkin)")
print("\n\n=== 4. None bilan saralash ===")
MALUMOT = [3, None, 1, None, 2]
print(f" Ro'yxat: {MALUMOT}\n")
try:
sorted(MALUMOT)
except TypeError as x:
print(f" sorted() → TypeError: {x}\n")
YECHIMLAR = [
("None oxirida", lambda x: (x is None, x if x is not None else 0)),
("None boshida", lambda x: (x is not None, x if x is not None else 0)),
("None → 0", lambda x: x if x is not None else 0),
("None → -inf", lambda x: x if x is not None else float("-inf")),
]
for nom, kalit in YECHIMLAR:
print(f" {nom:<16} {sorted(MALUMOT, key=kalit)}")
print("\n ⭐ (x is None, x) hiylasi: False(0) < True(1)")
print("\n\n=== 5. sort() natijasi ===")
r = [3, 1, 2]
natija = r.sort()
print(f" natija = r.sort()")
print(f" natija = {natija}")
print(f" r = {r}")
try:
[3, 1, 2].sort().reverse()
except AttributeError as x:
print(f"\n Zanjirlash: AttributeError: {x}")
print("\n ✅ To'g'ri:")
print(f" sorted([3,1,2], reverse=True) → {sorted([3, 1, 2], reverse=True)}")
print("\n\n=== 6. Sonlar satr sifatida ===")
SONLAR = ["10", "9", "100", "2"]
print(f" Satrlar: {SONLAR}\n")
print(f" sorted(): {sorted(SONLAR)} ← alifbo bo'yicha!")
print(f" key=int: {sorted(SONLAR, key=int)} ✅")
FAYLLAR = ["fayl10.txt", "fayl9.txt", "fayl100.txt", "fayl2.txt"]
print(f"\n Fayllar: {FAYLLAR}\n")
print(f" sorted(): {sorted(FAYLLAR)}")
import re
def tabiiy_kalit(s: str):
"""Raqamlarni son sifatida solishtiradi (natural sort)."""
return [int(q) if q.isdigit() else q.casefold()
for q in re.split(r"(\d+)", s)]
print(f" key=tabiiy_kalit: {sorted(FAYLLAR, key=tabiiy_kalit)} ✅")
print("\n\n=== 7. Float va NaN ===")
NAN = float("nan")
MALUMOT = [3.0, NAN, 1.0, 2.0]
print(f" Ro'yxat: {MALUMOT}")
print(f" sorted(): {sorted(MALUMOT)} ← natija KUTILMAGAN!")
print(f"""
Nega? NaN har qanday solishtirishda False qaytaradi:
NaN < 1 → {NAN < 1}
NaN > 1 → {NAN > 1}
NaN == NaN → {NAN == NAN}
Saralash algoritmi buzilib qoladi — xato bermaydi, jimgina noto'g'ri.
""")
import math
print(f" ✅ NaN ni filtrlang:")
toza = [x for x in MALUMOT if not math.isnan(x)]
print(f" {sorted(toza)}")Natijaning muhim qismi:
=== 3. Turli turlar ===
[3, 1, 2] → [1, 2, 3]
[1, True, 2.5] → [1, True, 2.5]
[1, '2', 3] → ❌ TypeError: '<' not supported between insta
[1, None, 2] → ❌ TypeError: '<' not supported between insta
=== 6. Sonlar satr sifatida ===
Satrlar: ['10', '9', '100', '2']
sorted(): ['10', '100', '2', '9'] ← alifbo bo'yicha!
key=int: ['2', '9', '10', '100'] ✅
Fayllar: ['fayl10.txt', 'fayl9.txt', 'fayl100.txt', 'fayl2.txt']
sorted(): ['fayl10.txt', 'fayl100.txt', 'fayl2.txt', 'fayl9.txt']
key=tabiiy_kalit: ['fayl2.txt', 'fayl9.txt', 'fayl10.txt', 'fayl100.txt'] ✅
=== 7. Float va NaN ===
sorted(): [3.0, nan, 1.0, 2.0] ← natija KUTILMAGAN!Nima ko'rsatdi: 2.5-bo'lim.
Misol 4 — Amaliy: hisobot generatori
"""Ko'p mezonli saralash bilan to'liq hisobot."""
from dataclasses import dataclass
from datetime import date
from operator import attrgetter
import heapq
import time
import random
@dataclass(frozen=True)
class Buyurtma:
raqam: int
mijoz: str
summa: int
sana: date
holat: str # "yangi" | "jarayonda" | "yakunlangan" | "bekor"
HOLAT_TARTIBI = {"yangi": 0, "jarayonda": 1, "yakunlangan": 2, "bekor": 3}
MIJOZLAR = ["Aziz", "Bobur", "Aziza", "Dilnoza", "Eldor", "Feruza"]
HOLATLAR = list(HOLAT_TARTIBI)
random.seed(42)
BUYURTMALAR = [
Buyurtma(
raqam=1000 + i,
mijoz=random.choice(MIJOZLAR),
summa=random.randrange(50_000, 5_000_000, 10_000),
sana=date(2026, random.randint(1, 9), random.randint(1, 28)),
holat=random.choice(HOLATLAR),
)
for i in range(40)
]
def jadval(buyurtmalar, sarlavha, n=None):
korsatiladi = buyurtmalar[:n] if n else buyurtmalar
qolgan = len(buyurtmalar) - len(korsatiladi)
print(f"\n ┌─ {sarlavha}")
print(f" │ {'№':<6} {'Mijoz':<10} {'Summa':>12} {'Sana':<12} Holat")
print(f" │ {'─' * 56}")
for b in korsatiladi:
print(f" │ {b.raqam:<6} {b.mijoz:<10} {b.summa:>12,} "
f"{b.sana.isoformat():<12} {b.holat}")
if qolgan:
print(f" │ ... yana {qolgan} ta")
print(f" └─")
print("=== 1. Bir mezon bo'yicha ===")
jadval(sorted(BUYURTMALAR, key=attrgetter("summa"), reverse=True),
"Eng katta summalar", 5)
jadval(sorted(BUYURTMALAR, key=attrgetter("sana")),
"Eng eski buyurtmalar", 5)
print("\n\n=== 2. Ko'p mezon: tuple kalit ===")
jadval(
sorted(BUYURTMALAR, key=lambda b: (HOLAT_TARTIBI[b.holat], -b.summa)),
"Holat bo'yicha, ichida summa kamayish tartibida",
12,
)
print("""
key = (HOLAT_TARTIBI[b.holat], -b.summa)
↑ maxsus tartib (alifbo emas) ↑ minus = kamayish
""")
print("\n=== 3. Ko'p mezon: ketma-ket saralash ===")
nusxa = list(BUYURTMALAR)
nusxa.sort(key=attrgetter("sana"), reverse=True) # 3-mezon
nusxa.sort(key=attrgetter("summa"), reverse=True) # 2-mezon
nusxa.sort(key=lambda b: HOLAT_TARTIBI[b.holat]) # 1-mezon
jadval(nusxa, "Holat → summa↓ → sana↓ (ketma-ket)", 12)
print("""
⚠️ Tartib TESKARI: eng kam muhim mezon AVVAL saralanadi.
Barqarorlik tufayli oldingi tartib saqlanadi.
""")
print("\n=== 4. Guruhlab hisobot ===")
from itertools import groupby
# groupby SARALANGAN ma'lumot talab qiladi!
saralangan = sorted(BUYURTMALAR, key=attrgetter("mijoz"))
print(f"\n {'Mijoz':<10} {'Soni':>5} {'Jami summa':>14} {'O''rtacha':>12}")
print(" " + "─" * 46)
qatorlar = []
for mijoz, guruh in groupby(saralangan, key=attrgetter("mijoz")):
ruyxat = list(guruh)
jami = sum(b.summa for b in ruyxat)
qatorlar.append((mijoz, len(ruyxat), jami, jami // len(ruyxat)))
# Jami summa bo'yicha saralash
for mijoz, soni, jami, ortacha in sorted(qatorlar, key=lambda q: -q[2]):
print(f" {mijoz:<10} {soni:>5} {jami:>14,} {ortacha:>12,}")
print("\n ⚠️ itertools.groupby SARALANGAN ma'lumot talab qiladi")
print(" (u faqat qo'shni bir xil elementlarni guruhlaydi)")
print("\n\n=== 5. Qisman saralash: heapq ===")
N = 500_000
KATTA = [random.randrange(10**9) for _ in range(N)]
K = 10
usullar = []
boshlandi = time.perf_counter()
r1 = sorted(KATTA, reverse=True)[:K]
usullar.append((f"sorted()[:{K}]", time.perf_counter() - boshlandi))
boshlandi = time.perf_counter()
r2 = heapq.nlargest(K, KATTA)
usullar.append((f"heapq.nlargest({K})", time.perf_counter() - boshlandi))
boshlandi = time.perf_counter()
r3 = [max(KATTA)]
usullar.append(("max()", time.perf_counter() - boshlandi))
assert r1 == r2
assert r3[0] == r1[0]
eng_tez = min(v for _, v in usullar)
print(f" {N:,} sondan eng katta {K} ta:\n")
print(f" {'Usul':<22} {'Vaqt':>10} {'Nisbat':>9}")
print(" " + "─" * 44)
for nom, vaqt in sorted(usullar, key=lambda x: x[1]):
print(f" {nom:<22} {vaqt * 1000:>7.1f} ms {vaqt / eng_tez:>8.1f}x")
print(f"""
Tavsiya:
k = 1 → max() / min()
k << n → heapq.nlargest(k, ...)
k ≈ n → sorted(...)[:k]
""")
print("\n=== 6. Timsort adaptivligi ===")
M = 1_000_000
SINOVLAR = [
("Allaqachon saralangan", list(range(M))),
("Teskari saralangan", list(range(M, 0, -1))),
("Deyarli saralangan", list(range(M))),
("Bloklarga bo'lingan", None),
("Tasodifiy", None),
]
# Deyarli saralangan — 100 ta elementni almashtirish
deyarli = SINOVLAR[2][1]
for _ in range(100):
i, j = random.randrange(M), random.randrange(M)
deyarli[i], deyarli[j] = deyarli[j], deyarli[i]
# Bloklarga bo'lingan — 10 ta saralangan blok
bloklar = []
for b in range(10):
bloklar.extend(range(b * M // 10, (b + 1) * M // 10))
SINOVLAR[3] = ("Bloklarga bo'lingan", bloklar)
tasodifiy = list(range(M))
random.shuffle(tasodifiy)
SINOVLAR[4] = ("Tasodifiy", tasodifiy)
print(f" {M:,} element:\n")
print(f" {'Ma`lumot turi':<26} {'Vaqt':>10} {'Nisbat':>9}")
print(" " + "─" * 48)
natijalar = []
for nom, malumot in SINOVLAR:
nusxa = malumot.copy()
boshlandi = time.perf_counter()
nusxa.sort()
natijalar.append((nom, time.perf_counter() - boshlandi))
eng_tez = min(v for _, v in natijalar)
for nom, vaqt in natijalar:
print(f" {nom:<26} {vaqt * 1000:>7.1f} ms {vaqt / eng_tez:>8.1f}x")
print("""
⭐ Timsort ADAPTIV:
saralangan ma'lumotda O(n),
tasodifiyda O(n log n).
Haqiqiy ma'lumot ko'pincha qisman saralangan —
shuning uchun Timsort amalda juda tez.
""")Natijaning muhim qismi:
=== 5. Qisman saralash: heapq ===
500,000 sondan eng katta 10 ta:
Usul Vaqt Nisbat
────────────────────────────────────────────
max() 8.4 ms 1.0x
heapq.nlargest(10) 31.2 ms 3.7x
sorted()[:10] 182.7 ms 21.7x
=== 6. Timsort adaptivligi ===
1,000,000 element:
Ma`lumot turi Vaqt Nisbat
────────────────────────────────────────────────
Allaqachon saralangan 5.1 ms 1.0x
Teskari saralangan 6.3 ms 1.2x
Deyarli saralangan 24.8 ms 4.9x
Bloklarga bo'lingan 41.2 ms 8.1x
Tasodifiy 412.6 ms 80.9xNima ko'rsatdi: 2.3, 2.6, 2.8-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"sort() saralangan ro'yxat qaytaradi" |
None. sorted() qaytaradi |
"sorted() asl turni qaytaradi" |
Doim list — hatto satrdan ham |
"key har solishtirish uchun chaqiriladi" |
Har element uchun bir marta |
"reverse=True = sorted()[::-1]" |
Barqarorlik boshqacha |
| "Barqarorlik — amalga oshirish tafsiloti" | Kafolatlangan xususiyat |
| "Ketma-ket saralashda asosiy mezon birinchi" | Oxirgi |
"sorted(["Olma", "anor"]) alifbo bo'yicha" |
Kod nuqtasi bo'yicha: O(79) < a(97) |
| "Har qanday ro'yxatni saralash mumkin" | Turlar solishtirilishi kerak |
| "Python sortni tezlashtirish mumkin" | Timsort — juda optimallashtirilgan |
6. Keng tarqalgan xatolar va yechimlari
1. sort() natijasini ishlatish
saralangan = royxat.sort() # ❌ None
saralangan = sorted(royxat) # ✅2. Registr muammosi
sorted(sozlar) # ❌ 'Olma' < 'anor'
sorted(sozlar, key=str.casefold) # ✅3. Sonlar satr sifatida
sorted(["10", "9", "2"]) # ❌ ['10', '2', '9']
sorted(["10", "9", "2"], key=int) # ✅ ['2', '9', '10']4. Ketma-ket saralashda tartib
r.sort(key=asosiy) # ❌ noto'g'ri tartib
r.sort(key=ikkilamchi)
r.sort(key=ikkilamchi) # ✅ avval ikkilamchi
r.sort(key=asosiy)5. [::-1] barqarorlikni buzadi
sorted(r, key=k)[::-1] # ❌
sorted(r, key=k, reverse=True) # ✅6. None bilan
sorted([1, None, 2]) # ❌ TypeError
sorted(m, key=lambda x: (x is None, x or 0)) # ✅7. groupby saralanmagan ma'lumotda
groupby(malumot, key=k) # ❌ noto'g'ri guruhlar
groupby(sorted(malumot, key=k), key=k) # ✅8. Katta ro'yxatdan bir nechta element
eng_kattalar = sorted(katta, reverse=True)[:10] # ❌ O(n log n)
eng_kattalar = heapq.nlargest(10, katta) # ✅ O(n log k)7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 6.2-dars (o'tilgan):
sortvareversemetodlari - 4.8-dars (o'tilgan): Unicode va kod nuqtalari — saralash tartibi
- 7-qism:
lambdava yuqori tartibli funksiyalar - 8-qism:
__lt__,functools.total_ordering,dataclass(order=True) - 10, 15-qismlar:
operatormoduli, funksional dasturlash - 15-qism:
heapq,itertools.groupby,collections - Ma'lumotlar bazasi:
ORDER BY— bir xil tushuncha
8. Eng yaxshi amaliyotlar
sorted()— sukut tanlov. Asl o'zgarmaydi, har qanday iterable bilan ishlaydi.sort()faqat aniq joyida o'zgartirish kerak bo'lganda.keyishlating,cmpemas.key— har element uchun bir marta,cmp_to_key— har solishtirish uchun.Ko'p mezon uchun tuple kalit.
key=lambda x: (a, b, c)— bir o'tishda.Turli yo'nalish — ketma-ket saralash. Eng kam muhim mezondan boshlab.
reverse=True,[::-1]emas. Barqarorlik saqlanadi.Satrlar uchun
key=str.casefold. O'zbekcha uchun apostrof normalizatsiyasi ham.operator.itemgetter/attrgetter.lambdadan tezroq va o'qilishi oson.k << n bo'lsa
heapq. To'liq saralash isrof.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. print(sorted([3, 1, 2]))
2. print([3, 1, 2].sort())
3. print(sorted("cba"))
4. print(sorted(["Olma", "anor"]))
5. print(sorted(["10", "9", "2"]))
6. print(sorted([-3, 1, -2], key=abs))
7. print(sorted([("a",1),("b",1)], key=lambda x: x[1], reverse=True))
8. print(sorted([("a",1),("b",1)], key=lambda x: x[1])[::-1])
9. print(sorted({"b": 2, "a": 1}))
10. print(sorted([1, True, 2.0]))Javoblar
[1, 2, 3]None['a', 'b', 'c']— list, satr emas['Olma', 'anor']—O(79) <a(97)['10', '2', '9']— alifbo bo'yicha[1, -2, -3][('a', 1), ('b', 1)]— barqaror[('b', 1), ('a', 1)]— teskari['a', 'b']— kalitlar[1, True, 2.0]—True == 1, barqarorlik tufayli asl tartib saqlanadi (1oldin kelgan edi)
Vazifa 2: key yozing
Har biri uchun key funksiyasi:
- So'zlarni oxirgi harfi bo'yicha
- Sonlarni raqamlari yig'indisi bo'yicha
- Fayllarni kengaytmasi, keyin nomi bo'yicha
- Ismlarni familiya bo'yicha (
"Aziz Karimov") - Versiyalarni to'g'ri (
"1.10.0" > "1.9.0") - Sanalarni satr shaklida (
"05.03.2026")
Javoblar
1. key=lambda s: s[-1]
2. key=lambda n: sum(int(c) for c in str(abs(n)))
3. key=lambda f: (f.rsplit(".", 1)[-1], f)
4. key=lambda i: i.split()[-1]
5. key=lambda v: tuple(int(x) for x in v.split("."))
6. key=lambda d: tuple(reversed(d.split(".")))Vazifa 3: Ko'p mezonli saralash
Xodimlar ro'yxatini saralang:
- Bo'lim (alifbo) → maosh (kamayish) → ism (alifbo)
- Bir usulni tuple kalit bilan, ikkinchisini ketma-ket saralash bilan
- Natijalar bir xilligini tekshiring
- Tezlikni solishtiring
Vazifa 4: Tabiiy saralash
tabiiy_kalit(s) funksiyasini yozing:
sorted(["fayl10", "fayl9", "fayl2"], key=tabiiy_kalit)
# ['fayl2', 'fayl9', 'fayl10']Qo'shimcha: registrsiz va o'zbek apostroflari bilan ishlashi kerak.
Vazifa 5: Saralash tahlilchisi
Dastur yozing:
- Turli ma'lumot turlarida (saralangan, teskari, tasodifiy, deyarli) tezlik
keybilan vakeysiz farqlambdavsitemgetterfarq- Natijani jadval +
█grafik ko'rinishida
Vazifa 6: Jadval sinfi
Jadval sinfini yozing:
sarala(ustun, kamayish=False)— barqarorlik bilanfiltr(shart)— filtrlashguruhla(ustun)—groupbybilaneng_kattalar(ustun, k)—heapqbilanchiqar()— chiroyli jadval- Zanjirlash:
j.filtr(...).sarala(...).chiqar()
Vazifa 7: O'ylash
Nega Python barqaror saralashni kafolatlaydi, garchi barqarorlik biroz qo'shimcha xotira talab qilsa ham?
Javob
Uch sabab.
1. Ko'p mezonli saralash oddiy bo'ladi.
Barqarorliksiz har safar to'liq tuple kalit yozish kerak:
# Barqarorliksiz — bitta murakkab kalit
sorted(x, key=lambda v: (v.a, -v.b, v.c.casefold(), ...))
# Barqarorlik bilan — sodda qadamlar
x.sort(key=attrgetter("c"))
x.sort(key=attrgetter("b"), reverse=True)
x.sort(key=attrgetter("a"))Ikkinchisi — turli yo'nalishlar bo'lganda yagona oson yechim. Satr uchun "minus" yo'q.
2. Foydalanuvchi interfeysi kutilgandek ishlaydi.
Jadvalda foydalanuvchi "Ball" ustunini bosadi, keyin "Guruh" ni bosadi. Barqarorlik tufayli natija — guruh bo'yicha, ichida ball bo'yicha. Bu — foydalanuvchi kutgan narsa, va u hech qanday qo'shimcha kodsiz ishlaydi.
Barqarorliksiz dasturchi saralash tarixini saqlab, murakkab kalit qurishi kerak edi.
3. Natija takrorlanuvchi (deterministik).
Barqarorliksiz bir xil kirish turli ishga tushirishlarda turli natija berishi mumkin (masalan, PYTHONHASHSEED yoki amalga oshirish tafsilotlariga qarab). Bu:
- Testlarni "flaky" qiladi
- Diff'larni shovqinli qiladi
- Xatolarni takrorlashni qiyinlashtiradi
Narxi qancha?
Timsort baribir merge sort asosida ishlaydi va O(n) qo'shimcha xotira talab qiladi. Barqarorlik — bu dizaynda bepul keladi. Barqaror bo'lmagan quicksort tezroq bo'lishi mumkin edi, lekin:
- Eng yomon holatda O(n²)
- Adaptiv emas (qisman saralangan ma'lumotda tez emas)
- Barqaror emas
Tim Peters bularning barchasini o'lchagan va Timsortni tanlagan. Java, Android, Swift, Rust ham keyinchalik shu tanlovni takrorlagan.
Xulosa: barqarorlik — "yaxshi bo'lardi" emas, balki API ning bir qismi. U ko'p mezonli saralashni Pythondagi eng oddiy amallardan biriga aylantirdi.
Nimani mustahkamlaydi: 2.2, 2.3, 2.4, 2.6, 2.8-bo'limlar.
Xulosa
Bu darsda saralashni chuqur o'rgandik.
Eng muhim uch fikr:
key— saralashning yuragi. U har element uchun bir marta chaqiriladi va natijasi bo'yicha saralanadi. Tuple qaytarsa — ko'p mezonli saralash bo'ladi.operator.itemgetter/attrgetter—lambdadan tezroq.Barqarorlik kafolatlangan. Teng kalitlar asl tartibini saqlaydi. Bu — ketma-ket saralash orqali turli yo'nalishdagi ko'p mezonli saralashni mumkin qiladi: eng kam muhim mezondan boshlang.
reverse=True,[::-1]emas. Birinchisi barqarorlikni saqlaydi, ikkinchisi buzadi. Vasort()Noneqaytaradi —sorted()yangi ro'yxat.
Keyingi darsda ro'yxat va xotira ni ko'ramiz: sys.getsizeof, o'sish strategiyasi, array moduli va qachon list o'rniga boshqa tuzilma kerakligi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!