Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Yaratish va {} tuzog'i
- 2.2. Nega in O(1) — hash jadvali
- 2.3. Element talablari — hashlanish
- 2.4. Asosiy metodlar
- 2.5. Tartibsizlik
- 2.6. Iteratsiya va o'zgartirish
- 2.7. Xotira va tezlik
- 2.8. set vs list vs dict
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Yaratish va asosiy amallar
- Misol 2 — Nega O(1)
- Misol 3 — Tartibsizlik va tuzoqlar
- Misol 4 — Amaliy: matn tahlili va deduplikatsiya
- 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.7-dars: set asoslari — noyob elementlar to'plami
6-QISM — MA'LUMOT TUZILMALARI · 7-dars
1. Kirish va motivatsiya
Ikki savol bilan boshlaymiz.
1. Ro'yxatdagi takrorlarni qanday olib tashlaysiz?
sozlar = ["olma", "anor", "olma", "behi", "anor", "olma"]
# ❌ Sekin va uzun
noyob = []
for s in sozlar:
if s not in noyob:
noyob.append(s)
# ✅ Bir qator
noyob = set(sozlar)2. Element ro'yxatda bormi — tekshirish qancha vaqt oladi?
import time
katta_royxat = list(range(1_000_000))
katta_toplam = set(katta_royxat)
# Ro'yxatda: O(n) — hamma elementni tekshiradi
999_999 in katta_royxat # ~15 ms
# To'plamda: O(1) — bitta hisoblash
999_999 in katta_toplam # ~0.00005 ms300 000 marta tezroq. Bu — dasturlashdagi eng katta "bir qator o'zgartirish" yutuqlaridan biri.
Lekin to'plamda tuzoqlar ham bor:
s = {}
print(type(s)) # dict! ← bo'sh to'plam emas
s = {1, 2, 3}
print(s[0]) # ❌ TypeError — indeks yo'q
s = {[1, 2]} # ❌ TypeError: unhashable type
s = {3, 1, 2}
print(s) # {1, 2, 3} ← saralangan? Yo'q, tasodifBu darsda:
- To'plam yaratish va
{}tuzog'i - Nega
inO(1) — hash jadvali - Barcha metodlar va ularning murakkabligi
- Tartibsizlik va uning oqibatlari
- Element talablari: hashlanish
setvslistvsdict— qachon qaysi biri
2. Nazariya — chuqur tushuntirish
2.1. Yaratish va {} tuzog'i
s = {1, 2, 3} # ✅ to'plam
s = set([1, 2, 3]) # ✅ ro'yxatdan
s = set("abc") # ✅ {'a', 'b', 'c'}
s = set() # ✅ BO'SH to'plam
s = {x for x in range(3)} # ✅ to'plam generatori (16-dars) Bo'sh to'plam — faqat set():
s = {}
print(type(s)) # <class 'dict'> ← LUG'AT!
s = set()
print(type(s)) # <class 'set'> ✅Sabab: {} sintaksisi lug'at uchun oldin band qilingan (Python 1.x), to'plam esa 2.4 da qo'shilgan. Orqaga moslik buzilmasligi uchun {} lug'at bo'lib qoldi.
Takrorlar avtomatik yo'qoladi:
{1, 2, 2, 3, 3, 3} # {1, 2, 3}
set("mississippi") # {'m', 'i', 's', 'p'}
len(set([1, 1, 1])) # 1 set(satr) — belgilarga bo'ladi:
set("abc") # {'a', 'b', 'c'}
{"abc"} # {'abc'} ← bitta elementHar qanday iterable'dan:
set([1, 2]) # ro'yxat
set((1, 2)) # tuple
set(range(3)) # range
set({"a": 1, "b": 2}) # {'a', 'b'} ← KALITLAR
set({"a": 1}.values()) # {1}2.2. Nega in O(1) — hash jadvali
To'plam ichkarida hash jadvali (hash table) — lug'at bilan bir xil tuzilma, faqat qiymatlarsiz.
Qanday ishlaydi:
s.add("olma")
1. hash("olma") → 8934572... (katta son)
2. 8934572 % jadval_hajmi → 5 (uyacha indeksi)
3. jadval[5] = "olma"
"olma" in s
1. hash("olma") → 8934572 (BIR XIL)
2. 8934572 % jadval_hajmi → 5
3. jadval[5] ni tekshirish → topildi ✅Bitta hisoblash — elementlar soniga bog'liq emas. Shuning uchun O(1).
Sxematik:
Ro'yxat: [olma] [anor] [behi] [uzum] [nok] ...
↑ tekshirish: birma-bir, o'rtacha n/2 ta solishtirish
To'plam (hash jadvali):
0: ─
1: ─
2: uzum
3: ─
4: nok
5: olma ← hash("olma") % 8 = 5 → darhol shu yerga
6: anor
7: behi
↑ tekshirish: bitta hisoblash + bitta solishtirishTo'qnashuvlar (collisions):
Ikki element bir xil uyachaga tushsa:
hash("a") % 8 == hash("b") % 8 # mumkinCPython ochiq adreslash (open addressing) ishlatadi — keyingi bo'sh uyachani qidiradi. Yuklanish 2/3 dan oshsa jadval kattalashadi.
Eng yomon holat — O(n):
Barcha element bir uyachaga tushsa. Amalda bu deyarli bo'lmaydi, chunki:
- CPython hash funksiyalari yaxshi taqsimlaydi
- Satrlar uchun hash randomizatsiyasi bor (
PYTHONHASHSEED) — HashDoS hujumidan himoya
Amaliy natija:
| Amal | list |
set |
|---|---|---|
x in s |
O(n) | O(1) |
add / append |
O(1) | O(1) |
remove |
O(n) | O(1) |
Indeks s[0] |
O(1) | yo'q |
| Tartib |
2.3. Element talablari — hashlanish
To'plam elementi hashlanadigan (hashable) bo'lishi kerak.
{1, 2, 3} # ✅ int
{"a", "b"} # ✅ str
{(1, 2), (3, 4)} # ✅ tuple
{frozenset([1, 2])} # ✅ frozenset
{None, True, 1.5} # ✅
{[1, 2]} # ❌ TypeError: unhashable type: 'list'
{{1, 2}} # ❌ unhashable type: 'set'
{{"a": 1}} # ❌ unhashable type: 'dict'Qoida: o'zgarmas obyektlar hashlanadi, o'zgaruvchanlar — yo'q.
Nega: hash element qiymatidan hisoblanadi. Element o'zgarsa hash ham o'zgaradi, va u jadvalda "yo'qolib qoladi":
# Agar ro'yxat hashlansa (tasavvur qiling):
r = [1, 2]
s = {r} # hash([1,2]) = 5 → jadval[5]
r.append(3) # endi hash([1,2,3]) = 9
r in s # jadval[9] ga qaraydi → topilmaydi! ❌Shuning uchun Python o'zgaruvchan obyektlarni hashlashni taqiqlaydi.
Ichma-ich tuzilmalar uchun frozenset yoki tuple:
{[1, 2], [3, 4]} # ❌
{(1, 2), (3, 4)} # ✅
{frozenset([1, 2]), frozenset([3, 4])} # ✅ (9-dars) 1, 1.0, True — bir xil:
{1, 1.0, True} # {1} ← hammasi teng va bir xil hash!
{0, 0.0, False} # {0}
{1, "1"} # {1, '1'} ← turliSabab: 1 == 1.0 == True va hash(1) == hash(1.0) == hash(True).
Birinchi qo'shilgani qoladi:
print({1, True}) # {1}
print({True, 1}) # {True}2.4. Asosiy metodlar
Qo'shish:
s = {1, 2}
s.add(3) # bitta element — O(1)
s.update([4, 5]) # ko'p element — O(k)
s.update([6], {7}, "89") # ko'p iterable
s |= {10} # update bilan bir xil add vs update:
s = {1, 2}
s.add([3, 4]) # ❌ TypeError — ro'yxat hashlanmaydi
s.add((3, 4)) # ✅ {1, 2, (3, 4)} — bitta element
s.update([3, 4]) # ✅ {1, 2, 3, 4} — ikki element
s.update("ab") # ✅ {1, 2, 'a', 'b'} ← satr belgilarga!Bu — list.append / list.extend bilan bir xil mantiq (6.2-dars).
Mavjud elementni qo'shish — xato emas:
s = {1, 2}
s.add(1) # ✅ hech narsa o'zgarmaydi
print(s) # {1, 2}O'chirish:
s = {1, 2, 3}
s.remove(1) # ❌ KeyError agar yo'q bo'lsa
s.discard(99) # ✅ yo'q bo'lsa jim turadi
s.pop() # ⚠️ TASODIFIY element, bo'sh bo'lsa KeyError
s.clear() # hammasini remove vs discard:
s = {1, 2}
s.remove(99) # ❌ KeyError: 99
s.discard(99) # ✅ hech narsa qilmaydi set.pop() — ro'yxatdan farqli:
r = [1, 2, 3]
r.pop() # 3 — OXIRGISI (aniq)
s = {1, 2, 3}
s.pop() # ? — TASODIFIY (aniqlanmagan)To'plamda "oxirgi" tushunchasi yo'q. Amalda hash jadvalidagi birinchi to'la uyacha qaytadi — bu ishga tushirishlar orasida o'zgarishi mumkin.
Nusxa:
s2 = s.copy() # sayoz nusxa
s2 = set(s) # bir xilBarcha o'zgartiruvchi metodlar None qaytaradi (6.2-dars kelishuvi):
natija = s.add(4) # None
natija = s.update([5]) # None
natija = s.discard(1) # None
x = s.pop() # ✅ element qaytaradi2.5. Tartibsizlik
To'plamda tartib yo'q — bu amalga oshirish tafsiloti emas, ta'rif.
s = {3, 1, 2}
print(s) # {1, 2, 3} ← saralangandek ko'rinadi Bu tasodif. Kichik butun sonlar uchun hash(n) == n, shuning uchun ular jadvalga tartib bilan tushadi. Boshqa turlar bilan:
print({"olma", "anor", "behi"})
# {'behi', 'olma', 'anor'} ← tasodifiy ko'rinadiSatrlar uchun tartib har ishga tushirishda o'zgaradi:
$ python -c "print({'a','b','c','d'})"
{'d', 'b', 'a', 'c'}
$ python -c "print({'a','b','c','d'})"
{'a', 'c', 'd', 'b'}Bu — hash randomizatsiyasi (PEP 456, Python 3.3+). Har jarayon boshlanganda tasodifiy urug' (seed) tanlanadi.
Nega: HashDoS hujumidan himoya. Hujumchi barchasi bir uyachaga tushadigan kalitlar yuborsa, dict/set O(n²) ga tushardi.
O'chirish (faqat testlar uchun):
PYTHONHASHSEED=0 python skript.pyAmaliy oqibatlar:
# ❌ To'plam tartibiga tayanmang
birinchi = list(s)[0] # har safar boshqa bo'lishi mumkin
# ❌ Testda to'plamni ro'yxat bilan solishtirmang
assert list(s) == ["a", "b"] # nomustaqil
# ✅ To'plam bilan solishtiring
assert s == {"a", "b"}
# ✅ Tartib kerak bo'lsa — saralang
for x in sorted(s):
...Tartibni saqlash kerak bo'lsa:
# Takrorlarni olib tashlash + tartib saqlash
noyob = list(dict.fromkeys(royxat)) # ✅ dict 3.7+ tartibni saqlaydi
# yoki
korilgan = set()
noyob = [x for x in royxat if not (x in korilgan or korilgan.add(x))]Birinchi variant o'qilishi ancha oson.
2.6. Iteratsiya va o'zgartirish
s = {1, 2, 3}
for x in s: # ✅ tartib aniqlanmagan
print(x)
len(s) # ✅
sum(s), min(s), max(s) # ✅
sorted(s) # ✅ list qaytaradi
list(s), tuple(s) # ✅Iteratsiya paytida o'zgartirish — xato:
s = {1, 2, 3}
for x in s:
if x == 2:
s.remove(x) # ❌ RuntimeError: Set changed size during iterationYechimlar:
# 1. Nusxa bo'yicha iteratsiya
for x in s.copy():
if shart(x):
s.remove(x)
# 2. Yangi to'plam (idiomatik)
s = {x for x in s if not shart(x)}
# 3. Farq amali
s -= {x for x in s if shart(x)}To'plamda indeks yo'q:
s[0] # ❌ TypeError: 'set' object is not subscriptable
s[0:2] # ❌Indeks kerak bo'lsa — list(s) yoki sorted(s).
2.7. Xotira va tezlik
import sys
sys.getsizeof(set()) # 216
sys.getsizeof({1}) # 216
sys.getsizeof({1, 2, 3, 4}) # 216
sys.getsizeof(set(range(5))) # 728
sys.getsizeof([1, 2, 3, 4]) # 88
sys.getsizeof({1, 2, 3, 4}) # 216 ← 2.5x ko'pTo'plam ro'yxatdan ~2-4x ko'p xotira oladi — bo'sh uyachalar kerak (yuklanish 2/3 dan oshmasligi uchun).
Bu — savdo:
list: kam xotira, sekin `in` (O(n))
set: ko'p xotira, tez `in` (O(1))Qachon foydali:
| Element soni | Tekshiruvlar soni | Tavsiya |
|---|---|---|
| < 10 | Har qanday | list (farq sezilmaydi) |
| Har qanday | 1 marta | list (to'plam qurish O(n)) |
| > 100 | Ko'p marta | set |
Bir marta tekshirish uchun to'plam qurish — isrof:
# ❌ To'plam qurish O(n), keyin bitta O(1) tekshiruv
if x in set(katta_royxat):
...
# ✅ To'g'ridan-to'g'ri
if x in katta_royxat:
...
# ✅ Ko'p tekshiruv bo'lsa — to'plamni bir marta quring
tekshirish = set(katta_royxat)
for x in qidiruvlar:
if x in tekshirish:
...2.8. set vs list vs dict
list |
set |
dict |
|
|---|---|---|---|
| Tartib | (3.7+) | ||
| Takrorlar | Kalitlar noyob | ||
| Indeks | Kalit bo'yicha | ||
in |
O(n) | O(1) | O(1) |
| Qo'shish | O(1) | O(1) | O(1) |
| O'chirish | O(n) | O(1) | O(1) |
| Element talabi | Har qanday | Hashlanadigan | Kalit hashlanadigan |
| Xotira (4 element) | 88 B | 216 B | 184 B |
| Qiymat saqlaydi |
Tanlash daraxti:
Kalit → qiymat kerakmi?
├── Ha → dict
└── Yo'q
├── Takrorlar kerakmi yoki tartib muhimmi?
│ ├── Ha → list
│ └── Yo'q
│ ├── Tez `in` kerakmi? → set
│ └── Yo'q → list (soddaroq)Amaliy misollar:
# ✅ set — noyoblik va tez tekshiruv
korilgan_id = set()
ruxsat_etilgan_turlar = {"jpg", "png", "webp"}
tashrif_buyurilgan = {(0, 0), (1, 1)}
# ✅ list — tartib va takrorlar
tarix = ["sahifa1", "sahifa2", "sahifa1"]
ballar = [90, 85, 90]
# ✅ dict — moslik
narxlar = {"non": 5000, "sut": 12000}3. Tez ma'lumotnoma
Yaratish
{1, 2, 3} to'plam
set() BO'SH to'plam ⭐
{} ❌ LUG'AT!
set([1, 2]) iterable'dan
set("abc") {'a','b','c'}
{"abc"} {'abc'} — bitta element
{x for x in r} generatorMetodlar
s.add(x) bitta element O(1)
s.update(it, ...) ko'p element O(k)
s.remove(x) ❌ KeyError agar yo'q O(1)
s.discard(x) ✅ jim turadi O(1)
s.pop() ⚠️ TASODIFIY element O(1)
s.clear() hammasini
s.copy() sayoz nusxa
x in s ⭐ O(1)
len(s), min, max, sum, sorted(s)Element talablari
{1, "a", (1,2), None, frozenset([1])} ✅ hashlanadi
{[1,2]}, {{1,2}}, {{"a":1}} ❌ unhashable
{1, 1.0, True} → {1} ← teng va bir xil hashTartibsizlik
{3,1,2} → {1,2,3} tasodif (hash(n)==n)
{'a','b'} har ishga tushirishda BOSHQA
→ PYTHONHASHSEED randomizatsiyasi
sorted(s) tartib kerak bo'lsa
list(dict.fromkeys(r)) takrorsiz + tartib saqlangan ⭐Qachon set
> 100 element + ko'p marta `in` → set ⭐
Bir marta tekshirish → list
Tartib yoki takror kerak → list
Xotira 2-4x ko'p → savdo4. Batafsil misollar
Misol 1 — Yaratish va asosiy amallar
"""To'plam yaratishning barcha usullari va tuzoqlar."""
import sys
print("=== 1. ⚠️ {} tuzog'i ===")
NAMUNALAR = [
("{}", {}),
("set()", set()),
("{1}", {1}),
("{1, 2, 3}", {1, 2, 3}),
("set([1, 2])", set([1, 2])),
("set('abc')", set("abc")),
("{'abc'}", {"abc"}),
("set(range(3))", set(range(3))),
("set({'a': 1})", set({"a": 1})),
("{x for x in '112'}", {x for x in "112"}),
]
print(f" {'Ifoda':<24} {'Turi':<8} {'Qiymat'}")
print(" " + "─" * 52)
for nom, q in NAMUNALAR:
print(f" {nom:<24} {type(q).__name__:<8} {q}")
print("""
⚠️ {} → LUG'AT, to'plam emas!
Sabab: {} lug'at uchun oldin band qilingan (Python 1.x),
to'plam esa 2.4 da qo'shilgan.
""")
print("\n=== 2. Takrorlar avtomatik yo'qoladi ===")
SINOVLAR = [
("[1, 2, 2, 3, 3, 3]", [1, 2, 2, 3, 3, 3]),
("'mississippi'", "mississippi"),
("['a', 'A', 'a']", ["a", "A", "a"]),
("[1, 1.0, True]", [1, 1.0, True]),
("[0, 0.0, False]", [0, 0.0, False]),
("[1, '1']", [1, "1"]),
("[(1,2), (1,2), (2,1)]", [(1, 2), (1, 2), (2, 1)]),
]
print(f" {'Kirish':<26} {'len':>4} → {'To`plam':<24} {'len':>4}")
print(" " + "─" * 68)
for nom, malumot in SINOVLAR:
s = set(malumot)
print(f" {nom:<26} {len(malumot):>4} → {str(s):<24} {len(s):>4}")
print("""
⚠️ 1, 1.0, True — TENG va bir xil hash → bitta element
Qaysi biri qoladi? BIRINCHI qo'shilgani.
""")
print(f" {{1, True}} = {{1, True}}")
print(f" {{True, 1}} = {{True, 1}}")
print("\n=== 3. Element talablari ===")
SINOVLAR = [
("1", 1),
("'abc'", "abc"),
("(1, 2)", (1, 2)),
("None", None),
("1.5", 1.5),
("frozenset([1, 2])", frozenset([1, 2])),
("[1, 2]", [1, 2]),
("{1, 2}", {1, 2}),
("{'a': 1}", {"a": 1}),
("(1, [2])", (1, [2])),
("bytearray(b'ab')", bytearray(b"ab")),
("b'ab'", b"ab"),
]
print(f" {'Element':<22} {'set ga qo`shish'}")
print(" " + "─" * 60)
for nom, q in SINOVLAR:
try:
s = {q}
natija = f"✅ {s}"
except TypeError as x:
natija = f"❌ {x}"
print(f" {nom:<22} {natija}")
print("""
⭐ Qoida: o'zgarmas → hashlanadi → to'plamga qo'shiladi
""")
print("\n=== 4. Metodlar ===")
s = {1, 2, 3}
print(f" Boshlang'ich: {s}\n")
AMALLAR = [
("s.add(4)", lambda s: s.add(4)),
("s.add(1)", lambda s: s.add(1)),
("s.update([5, 6])", lambda s: s.update([5, 6])),
("s.update('ab')", lambda s: s.update("ab")),
("s.update([7], {8})", lambda s: s.update([7], {8})),
]
for kod, f in AMALLAR:
nusxa = s.copy()
natija = f(nusxa)
print(f" {kod:<22} → {sorted(nusxa, key=str)} (qaytardi: {natija})")
print(f"\n ⚠️ add vs update:")
n1 = {1, 2}
n1.add((3, 4))
print(f" s.add((3, 4)) → {n1} ← BITTA element")
n2 = {1, 2}
n2.update([3, 4])
print(f" s.update([3, 4]) → {n2} ← IKKI element")
n3 = {1, 2}
try:
n3.add([3, 4])
except TypeError as x:
print(f" s.add([3, 4]) → ❌ {x}")
print("\n=== 5. O'chirish ===")
s = {1, 2, 3, 4, 5}
print(f" Boshlang'ich: {s}\n")
nusxa = s.copy()
nusxa.remove(1)
print(f" s.remove(1) → {nusxa}")
try:
nusxa.remove(99)
except KeyError as x:
print(f" s.remove(99) → ❌ KeyError: {x}")
nusxa = s.copy()
nusxa.discard(2)
nusxa.discard(99)
print(f" s.discard(2) → {nusxa}")
print(f" s.discard(99) → ✅ xato yo'q")
nusxa = s.copy()
olingan = nusxa.pop()
print(f"\n s.pop() → {olingan} olindi, qoldi: {nusxa}")
print(f" ⚠️ TASODIFIY element!")
try:
set().pop()
except KeyError as x:
print(f" set().pop() → ❌ KeyError: {x}")
nusxa = s.copy()
nusxa.clear()
print(f"\n s.clear() → {nusxa}")
print("\n=== 6. ⚠️ Tartibsizlik ===")
SINOVLAR = [
("Kichik butun sonlar", {5, 3, 1, 4, 2}),
("Katta butun sonlar", {5000, 3000, 1000, 4000}),
("Satrlar", {"olma", "anor", "behi", "uzum"}),
("Aralash", {1, "a", 2.5, (3, 4), None}),
]
for nom, s in SINOVLAR:
print(f" {nom:<24} {s}")
print("""
⚠️ Kichik butun sonlar saralangandek ko'rinadi —
bu TASODIF: hash(n) == n bo'lgani uchun.
⚠️ Satrlar tartibi HAR ISHGA TUSHIRISHDA boshqacha —
hash randomizatsiyasi (PEP 456, HashDoS himoyasi).
""")
print(" Buni sinash uchun terminalda ikki marta ishga tushiring:")
print(" python -c \"print({'a','b','c','d'})\"")
print("\n=== 7. Xotira ===")
print(f" {'n':>6} {'list':>9} {'set':>9} {'dict':>9} {'nisbat'}")
print(" " + "─" * 48)
for n in [0, 1, 4, 5, 10, 100, 1000, 10000]:
r = list(range(n))
s = set(range(n))
d = dict.fromkeys(range(n))
hr, hs, hd = sys.getsizeof(r), sys.getsizeof(s), sys.getsizeof(d)
print(f" {n:>6} {hr:>9,} {hs:>9,} {hd:>9,} {hs / max(hr, 1):>7.1f}x")
print("""
To'plam ~2-4x ko'p xotira oladi — bo'sh uyachalar kerak.
Bu — tezlik uchun to'lanadigan narx.
""")Natijaning muhim qismi:
=== 1. ⚠️ {} tuzog'i ===
Ifoda Turi Qiymat
────────────────────────────────────────────────────
{} dict {}
set() set set()
set('abc') set {'a', 'c', 'b'}
{'abc'} set {'abc'}
set({'a': 1}) set {'a'}
=== 2. Takrorlar avtomatik yo'qoladi ===
Kirish len → To`plam len
────────────────────────────────────────────────────────────────────
'mississippi' 11 → {'p', 'm', 's', 'i'} 4
[1, 1.0, True] 3 → {1} 1
[0, 0.0, False] 3 → {0} 1
[1, '1'] 2 → {1, '1'} 2
=== 7. Xotira ===
n list set dict nisbat
────────────────────────────────────────────────
4 88 216 224 2.5x
100 856 8,408 4,688 9.8x
1000 8,056 32,984 36,952 4.1xNima ko'rsatdi: 2.1, 2.3, 2.4, 2.5, 2.7-bo'limlar.
Misol 2 — Nega O(1)
"""Hash jadvali va tezlik namoyishi."""
import sys
import time
import random
print("=== 1. `in` tezligi: list vs set ===")
HAJMLAR = [100, 1_000, 10_000, 100_000, 1_000_000]
TEKSHIRUVLAR = 1_000
print(f" {TEKSHIRUVLAR:,} ta tekshiruv:\n")
print(f" {'n':>10} {'list':>12} {'set':>12} {'dict':>12} {'set tezligi':>13}")
print(" " + "─" * 64)
for n in HAJMLAR:
r = list(range(n))
s = set(r)
d = dict.fromkeys(r)
random.seed(1)
qidiruvlar = [random.randrange(n * 2) for _ in range(TEKSHIRUVLAR)]
boshlandi = time.perf_counter()
for q in qidiruvlar:
_ = q in r
vaqt_list = time.perf_counter() - boshlandi
boshlandi = time.perf_counter()
for q in qidiruvlar:
_ = q in s
vaqt_set = time.perf_counter() - boshlandi
boshlandi = time.perf_counter()
for q in qidiruvlar:
_ = q in d
vaqt_dict = time.perf_counter() - boshlandi
print(f" {n:>10,} {vaqt_list * 1000:>10.2f}ms "
f"{vaqt_set * 1000:>10.2f}ms {vaqt_dict * 1000:>10.2f}ms "
f"{vaqt_list / vaqt_set:>11,.0f}x")
print("""
⭐ list: O(n) — n oshgan sari sekinlashadi
set: O(1) — n ga BOG'LIQ EMAS
""")
print("\n=== 2. Hash jadvali qanday ishlaydi ===")
def uyacha_korsat(elementlar, jadval_hajmi=8):
"""Soddalashtirilgan hash jadvali namoyishi."""
uyachalar = [[] for _ in range(jadval_hajmi)]
for x in elementlar:
i = hash(x) % jadval_hajmi
uyachalar[i].append(x)
return uyachalar
MEVALAR = ["olma", "anor", "behi", "uzum", "nok"]
print(f" Elementlar: {MEVALAR}\n")
print(f" {'Element':<10} {'hash()':>22} {'% 8':>5}")
print(" " + "─" * 42)
for x in MEVALAR:
h = hash(x)
print(f" {x:<10} {h:>22} {h % 8:>5}")
print(f"\n Jadval (8 uyacha):")
for i, uyacha in enumerate(uyacha_korsat(MEVALAR)):
belgi = ", ".join(uyacha) if uyacha else "─"
ogoh = " ⚠️ TO'QNASHUV" if len(uyacha) > 1 else ""
print(f" [{i}] {belgi}{ogoh}")
print("""
⭐ Qidirish: hash(x) % 8 → darhol kerakli uyacha.
Elementlar sonidan qat'i nazar — bitta hisoblash.
""")
print("\n=== 3. To'qnashuvlar ===")
class YomonHash:
"""BARCHA obyekt bir xil hash — eng yomon holat."""
def __init__(self, q):
self.q = q
def __hash__(self):
return 42 # ⚠️ hammasi bir xil!
def __eq__(self, boshqa):
return isinstance(boshqa, YomonHash) and self.q == boshqa.q
class YaxshiHash:
def __init__(self, q):
self.q = q
def __hash__(self):
return hash(self.q)
def __eq__(self, boshqa):
return isinstance(boshqa, YaxshiHash) and self.q == boshqa.q
N = 2_000
for sinf, nom in [(YaxshiHash, "Yaxshi hash"), (YomonHash, "Yomon hash (hammasi 42)")]:
obyektlar = [sinf(i) for i in range(N)]
boshlandi = time.perf_counter()
s = set(obyektlar)
qurish = time.perf_counter() - boshlandi
qidiruvlar = obyektlar[::10]
boshlandi = time.perf_counter()
for o in qidiruvlar:
_ = o in s
qidirish = time.perf_counter() - boshlandi
print(f" {nom:<26} qurish: {qurish * 1000:>8.1f}ms "
f"qidirish: {qidirish * 1000:>8.1f}ms")
print("""
⚠️ Barcha element bir uyachaga tushsa — to'plam ro'yxatga aylanadi: O(n).
Bu — HashDoS hujumining asosi. CPython buni
hash randomizatsiyasi bilan oldini oladi.
""")
print("\n=== 4. Qachon to'plam foydali ===")
print(""" Savol: to'plam qurish O(n). Nechta tekshiruvdan keyin foyda beradi?\n""")
N = 100_000
r = list(range(N))
random.seed(2)
print(f" Ro'yxat hajmi: {N:,}\n")
print(f" {'Tekshiruvlar':>13} {'list':>12} {'set (qurish+)':>15} {'Foydalimi'}")
print(" " + "─" * 56)
for k in [1, 5, 10, 50, 100, 1000]:
qidiruvlar = [random.randrange(N * 2) for _ in range(k)]
boshlandi = time.perf_counter()
for q in qidiruvlar:
_ = q in r
vaqt_list = time.perf_counter() - boshlandi
boshlandi = time.perf_counter()
s = set(r)
for q in qidiruvlar:
_ = q in s
vaqt_set = time.perf_counter() - boshlandi
foydali = "✅ ha" if vaqt_set < vaqt_list else "❌ yo'q"
print(f" {k:>13,} {vaqt_list * 1000:>10.2f}ms "
f"{vaqt_set * 1000:>13.2f}ms {foydali}")
print("""
⭐ Bir-ikki tekshiruv uchun to'plam qurish — ISROF.
Ko'p tekshiruv bo'lsa — katta yutuq.
""")
print("\n=== 5. Takrorlarni olib tashlash ===")
N = 200_000
random.seed(3)
MALUMOT = [random.randrange(N // 2) for _ in range(N)]
USULLAR = []
# 1. Sikl + in (❌ O(n²))
boshlandi = time.perf_counter()
noyob = []
for x in MALUMOT[:3000]: # 100x kam!
if x not in noyob:
noyob.append(x)
USULLAR.append(("sikl + `in` (O(n²))", (time.perf_counter() - boshlandi) * 66))
# 2. set (tartib yo'qoladi)
boshlandi = time.perf_counter()
noyob = list(set(MALUMOT))
USULLAR.append(("set(...)", time.perf_counter() - boshlandi))
# 3. dict.fromkeys (tartib saqlanadi) ⭐
boshlandi = time.perf_counter()
noyob = list(dict.fromkeys(MALUMOT))
USULLAR.append(("dict.fromkeys(...) ⭐", time.perf_counter() - boshlandi))
# 4. Ko'rilganlar to'plami
boshlandi = time.perf_counter()
korilgan = set()
noyob = []
for x in MALUMOT:
if x not in korilgan:
korilgan.add(x)
noyob.append(x)
USULLAR.append(("korilgan to'plami", time.perf_counter() - boshlandi))
eng_tez = min(v for _, v in USULLAR)
print(f" {N:,} elementdan takrorlarni olib tashlash:\n")
print(f" {'Usul':<26} {'Vaqt':>10} {'Nisbat':>10} {'Tartib'}")
print(" " + "─" * 60)
for nom, vaqt in sorted(USULLAR, key=lambda x: x[1]):
tartib = "❌" if "set(" in nom else "✅"
taxmin = "~" if "O(n²)" in nom else " "
print(f" {nom:<26} {taxmin}{vaqt * 1000:>8.1f} ms "
f"{vaqt / eng_tez:>9.1f}x {tartib}")
print("""
⭐ Tartib kerak bo'lsa — dict.fromkeys()
Tartib kerak bo'lmasa — set()
Hech qachon — sikl + `in`
""")Natijaning muhim qismi:
=== 1. `in` tezligi: list vs set ===
1,000 ta tekshiruv:
n list set dict set tezligi
────────────────────────────────────────────────────────────────
100 0.42ms 0.05ms 0.05ms 9x
1,000 3.81ms 0.05ms 0.05ms 76x
10,000 38.24ms 0.05ms 0.05ms 765x
100,000 382.10ms 0.05ms 0.05ms 7,642x
1,000,000 15260.74ms 0.42ms 0.52ms 36,077x
=== 3. To'qnashuvlar ===
Yaxshi hash qurish: 1.2ms qidirish: 0.1ms
Yomon hash (hammasi 42) qurish: 1842.3ms qidirish: 184.2ms
=== 4. Qachon to'plam foydali ===
Tekshiruvlar list set (qurish+) Foydalimi
────────────────────────────────────────────────────────
1 0.38ms 2.14ms ❌ yo'q
10 3.82ms 2.15ms ✅ ha
1,000 382.14ms 2.21ms ✅ haNima ko'rsatdi: 2.2, 2.7-bo'limlar.
Misol 3 — Tartibsizlik va tuzoqlar
"""To'plam bilan ishlashdagi keng tarqalgan xatolar."""
import random
print("=== 1. Tartibga tayanish ===")
s = {"olma", "anor", "behi", "uzum"}
print(f" To'plam: {s}\n")
print(" ❌ Xavfli kod:")
print(f" list(s)[0] = {list(s)[0]!r} ← har ishga tushirishda BOSHQA")
print(f" s.pop() = tasodifiy element")
print(f" next(iter(s)) = {next(iter(s))!r} ← ham tasodifiy")
print("\n ✅ Xavfsiz:")
print(f" sorted(s)[0] = {sorted(s)[0]!r} ← aniq")
print(f" min(s) = {min(s)!r} ← aniq")
print(f" sorted(s) = {sorted(s)}")
print("""
⚠️ Testlarda:
assert list(s) == ["a", "b"] ❌ nomustaqil
assert s == {"a", "b"} ✅
assert sorted(s) == ["a", "b"] ✅
""")
print("\n=== 2. Kichik sonlar aldashi ===")
SINOVLAR = [
("Kichik sonlar 1-10", set(range(1, 11))),
("Kichik sonlar aralash", {7, 2, 9, 4, 1}),
("Katta sonlar", {7000, 2000, 9000, 4000, 1000}),
("Manfiy sonlar", {-3, -1, -2, 0, 1}),
("Float", {1.5, 0.5, 2.5}),
("Satrlar", {"e", "b", "a", "d", "c"}),
]
for nom, s in SINOVLAR:
print(f" {nom:<24} {s}")
print(f"\n hash() qiymatlari:")
for x in [1, 5, 100, -1, -2, 1.5, 2.0]:
print(f" hash({x!r:>5}) = {hash(x)}")
print("""
⭐ Kichik musbat butun sonlar uchun hash(n) == n →
ular jadvalga tartib bilan tushadi → saralangandek ko'rinadi.
⚠️ hash(-1) == -2 — CPython da -1 xato belgisi sifatida band.
""")
print("\n=== 3. Iteratsiya paytida o'zgartirish ===")
s = {1, 2, 3, 4, 5}
print(f" To'plam: {s}\n")
print(" ❌ Xato:")
try:
nusxa = s.copy()
for x in nusxa:
if x % 2 == 0:
nusxa.remove(x)
except RuntimeError as x:
print(f" for x in s: s.remove(x) → RuntimeError: {x}")
print("\n ✅ Uch yechim:")
n1 = s.copy()
for x in n1.copy():
if x % 2 == 0:
n1.remove(x)
print(f" 1. for x in s.copy(): → {sorted(n1)}")
n2 = {x for x in s if x % 2 != 0}
print(f" 2. {{x for x in s if ...}} → {sorted(n2)}")
n3 = s.copy()
n3 -= {x for x in n3 if x % 2 == 0}
print(f" 3. s -= {{x for x in s ...}} → {sorted(n3)}")
print("\n=== 4. Indeks yo'q ===")
s = {10, 20, 30}
print(f" To'plam: {s}\n")
AMALLAR = [
("s[0]", lambda: s[0]),
("s[0:2]", lambda: s[0:2]),
("s.index(10)", lambda: s.index(10)),
("s.sort()", lambda: s.sort()),
("s + {40}", lambda: s + {40}),
("s * 2", lambda: s * 2),
]
for kod, f in AMALLAR:
try:
natija = f"✅ {f()}"
except (TypeError, AttributeError) as x:
natija = f"❌ {type(x).__name__}: {x}"
print(f" {kod:<14} {natija}")
print("\n ✅ Muqobillar:")
print(f" list(s)[0] → {list(s)[0]} (tasodifiy)")
print(f" sorted(s)[0] → {sorted(s)[0]} (aniq)")
print(f" s | {{40}} → {s | {40}}")
print(f" sorted(s) → {sorted(s)}")
print("\n=== 5. add vs update ===")
MANBALAR = [
("[3, 4]", [3, 4]),
("(3, 4)", (3, 4)),
("'ab'", "ab"),
("{3, 4}", {3, 4}),
("range(2)", range(2)),
("5", 5),
]
print(f" {'Manba':<12} {'add(x)':<26} {'update(x)'}")
print(" " + "─" * 60)
for nom, manba in MANBALAR:
a = {1, 2}
try:
a.add(manba)
add_natija = str(sorted(a, key=str))
except TypeError:
add_natija = "❌ unhashable"
b = {1, 2}
try:
b.update(manba)
upd_natija = str(sorted(b, key=str))
except TypeError:
upd_natija = "❌ not iterable"
print(f" {nom:<12} {add_natija:<26} {upd_natija}")
print("""
⭐ add — BITTA element (hashlanishi kerak)
update — HAR BIR element (iterable bo'lishi kerak)
""")
print("\n=== 6. remove vs discard vs pop ===")
print(f" {'Amal':<20} {'Element bor':<22} {'Element yo`q'}")
print(" " + "─" * 62)
for kod in ["s.remove(x)", "s.discard(x)"]:
natijalar = []
for x in [1, 99]:
s = {1, 2, 3}
try:
if "remove" in kod:
s.remove(x)
else:
s.discard(x)
natijalar.append(f"✅ {sorted(s)}")
except KeyError:
natijalar.append("❌ KeyError")
print(f" {kod:<20} {natijalar[0]:<22} {natijalar[1]}")
print(f"\n s.pop() — tasodifiy element:")
for _ in range(3):
s = {"olma", "anor", "behi", "uzum"}
olingan = s.pop()
print(f" pop() → {olingan!r:<8} qoldi: {sorted(s)}")
print("""
⚠️ set.pop() — list.pop() dan FARQLI:
list.pop() → OXIRGISI (aniq)
set.pop() → tasodifiy (tartib yo'q)
""")
print("\n=== 7. 1 == 1.0 == True tuzog'i ===")
SINOVLAR = [
"{1, 1.0, True}",
"{0, 0.0, False}",
"{1, True, 'True'}",
"{1.0, 1, 2}",
"{(1,), (1.0,)}",
"{frozenset([1]), frozenset([1.0])}",
]
for kod in SINOVLAR:
print(f" {kod:<38} → {eval(kod)}")
print(f"\n Sabab:")
for a, b in [(1, 1.0), (1, True), (0, False), (1.0, True)]:
print(f" {a!r:<6} == {b!r:<6} {a == b:<6} "
f"hash teng: {hash(a) == hash(b)}")
print("""
⚠️ Bu — real muammo:
ID lar {1, 2, 3} va bayroqlar {True, False} bir to'plamda
bo'lsa, 1 va True birlashib ketadi.
""")
IDLAR = {1, 2, 3}
BAYROQLAR = {True, False}
print(f" IDLAR | BAYROQLAR = {IDLAR | BAYROQLAR}")
print(f" ⚠️ True yo'qoldi — u 1 bilan bir xil!")Natijaning muhim qismi:
=== 4. Indeks yo'q ===
To'plam: {10, 20, 30}
s[0] ❌ TypeError: 'set' object is not subscriptable
s[0:2] ❌ TypeError: 'set' object is not subscriptable
s.index(10) ❌ AttributeError: 'set' object has no attribute 'index'
s.sort() ❌ AttributeError: 'set' object has no attribute 'sort'
s + {40} ❌ TypeError: unsupported operand type(s) for +: 'set' and 'set'
s * 2 ❌ TypeError: unsupported operand type(s) for *: 'set' and 'int'
=== 7. 1 == 1.0 == True tuzog'i ===
{1, 1.0, True} → {1}
{0, 0.0, False} → {0}
{1, True, 'True'} → {'True', 1}
{(1,), (1.0,)} → {(1,)}
IDLAR | BAYROQLAR = {False, 1, 2, 3}
⚠️ True yo'qoldi — u 1 bilan bir xil!Nima ko'rsatdi: 2.3, 2.4, 2.5, 2.6-bo'limlar.
Misol 4 — Amaliy: matn tahlili va deduplikatsiya
"""To'plamning haqiqiy vazifalarda qo'llanishi."""
import re
import time
import random
from collections import Counter
print("=== 1. Matn tahlili ===")
MATN = """
Python — kuchli va oddiy dasturlash tili. Python o'rganish oson,
lekin uning imkoniyatlari juda keng. Dasturlash tili sifatida
Python veb, ma'lumot tahlili va sun'iy intellektda ishlatiladi.
Oddiy sintaksis Python ni yangi boshlovchilar uchun ideal qiladi.
"""
TOXTASH_SOZLARI = {
"va", "u", "bu", "uchun", "bilan", "lekin", "yoki",
"ham", "ni", "ning", "da", "dan", "ga", "sifatida",
}
def sozlarga(matn: str) -> list[str]:
return re.findall(r"[a-zA-Zʻʼ'Ѐ-ӿ]+", matn.lower())
sozlar = sozlarga(MATN)
noyob = set(sozlar)
mazmunli = noyob - TOXTASH_SOZLARI
print(f" Jami so'zlar: {len(sozlar)}")
print(f" Noyob so'zlar: {len(noyob)}")
print(f" Takrorlanish: {len(sozlar) / len(noyob):.2f}x")
print(f" To'xtash so'zlari: {len(noyob & TOXTASH_SOZLARI)}")
print(f" Mazmunli so'zlar: {len(mazmunli)}")
print(f"\n Eng ko'p uchraganlar:")
for soz, soni in Counter(s for s in sozlar if s not in TOXTASH_SOZLARI).most_common(5):
print(f" {soz:<14} {'█' * soni} {soni}")
print(f"\n Faqat bir marta uchraganlar ({len([s for s in noyob if sozlar.count(s) == 1])} ta):")
bir_martalik = sorted(s for s in mazmunli if sozlar.count(s) == 1)
print(f" {', '.join(bir_martalik[:10])}...")
print("\n\n=== 2. Ruxsat tizimi ===")
class Foydalanuvchi:
def __init__(self, ism: str, rollar: set[str]):
self.ism = ism
self.rollar = rollar
ROL_RUXSATLARI = {
"mehmon": {"oqish"},
"foydalanuvchi": {"oqish", "izoh_yozish"},
"muallif": {"oqish", "izoh_yozish", "maqola_yozish", "maqola_tahrirlash"},
"moderator": {"oqish", "izoh_yozish", "izoh_ochirish", "foydalanuvchi_bloklash"},
"admin": {"oqish", "izoh_yozish", "maqola_yozish", "maqola_tahrirlash",
"izoh_ochirish", "foydalanuvchi_bloklash", "sozlamalar"},
}
def ruxsatlar(f: Foydalanuvchi) -> set[str]:
"""Barcha rollardan ruxsatlarni birlashtiradi."""
natija = set()
for rol in f.rollar:
natija |= ROL_RUXSATLARI.get(rol, set())
return natija
def ruxsat_bormi(f: Foydalanuvchi, kerakli: set[str]) -> bool:
return kerakli <= ruxsatlar(f) # qism to'plam
FOYDALANUVCHILAR = [
Foydalanuvchi("Aziz", {"admin"}),
Foydalanuvchi("Bobur", {"muallif", "moderator"}),
Foydalanuvchi("Aziza", {"foydalanuvchi"}),
Foydalanuvchi("Mehmon", {"mehmon"}),
]
TEKSHIRUVLAR = [
("Maqola yozish", {"maqola_yozish"}),
("Izoh o'chirish", {"izoh_ochirish"}),
("Sozlamalar", {"sozlamalar"}),
("Yozish + o'chirish", {"maqola_yozish", "izoh_ochirish"}),
]
sarlavha = f" {'Foydalanuvchi':<14} {'Ruxsatlar':>10}"
for nom, _ in TEKSHIRUVLAR:
sarlavha += f" {nom:>20}"
print(sarlavha)
print(" " + "─" * (26 + 21 * len(TEKSHIRUVLAR)))
for f in FOYDALANUVCHILAR:
qator = f" {f.ism:<14} {len(ruxsatlar(f)):>10}"
for _, kerakli in TEKSHIRUVLAR:
qator += f" {'✅' if ruxsat_bormi(f, kerakli) else '❌':>19}"
print(qator)
print(f"\n Bobur ruxsatlari (muallif + moderator):")
for r in sorted(ruxsatlar(FOYDALANUVCHILAR[1])):
print(f" • {r}")
print("\n\n=== 3. Deduplikatsiya — email ro'yxati ===")
XOM_EMAILLAR = [
"Aziz@Mail.uz",
"aziz@mail.uz",
" bobur@mail.uz ",
"BOBUR@MAIL.UZ",
"aziza@mail.uz",
"aziz@mail.uz",
"noto'g'ri-email",
"dilnoza@mail.uz",
"aziza@Mail.UZ",
"",
]
def normalla(email: str) -> str | None:
email = email.strip().lower()
if not re.fullmatch(r"[\w.+-]+@[\w-]+\.[\w.]+", email):
return None
return email
toza = set()
notogri = []
for e in XOM_EMAILLAR:
n = normalla(e)
if n is None:
notogri.append(e)
else:
toza.add(n)
print(f" Xom ro'yxat: {len(XOM_EMAILLAR)}")
print(f" Noto'g'ri: {len(notogri)} {notogri}")
print(f" Noyob to'g'ri: {len(toza)}\n")
for e in sorted(toza):
print(f" ✅ {e}")
print("""
⭐ Normalizatsiya + to'plam = deduplikatsiya.
'Aziz@Mail.uz' va 'aziz@mail.uz' bitta odam.
""")
print("\n=== 4. Takrorlarni topish ===")
random.seed(5)
BUYURTMALAR = [f"BUY-{random.randrange(1000, 1100)}" for _ in range(50)]
korilgan = set()
takrorlar = set()
for b in BUYURTMALAR:
if b in korilgan:
takrorlar.add(b)
korilgan.add(b)
print(f" Jami buyurtmalar: {len(BUYURTMALAR)}")
print(f" Noyob raqamlar: {len(korilgan)}")
print(f" Takrorlangan: {len(takrorlar)}")
if takrorlar:
print(f"\n Takrorlar (nechta marta):")
hisob = Counter(BUYURTMALAR)
for raqam in sorted(takrorlar)[:5]:
print(f" {raqam} ×{hisob[raqam]}")
# Bir o'tishda
print(f"\n Bir qatorda:")
print(f" takrorlar = {{x for x in b if b.count(x) > 1}} ⚠️ O(n²)")
print(f" takrorlar = {{x for x, n in Counter(b).items() if n > 1}} ✅ O(n)")
print("\n\n=== 5. Grafik: do'stlar tarmog'i ===")
DOSTLAR = {
"Aziz": {"Bobur", "Aziza", "Eldor"},
"Bobur": {"Aziz", "Dilnoza"},
"Aziza": {"Aziz", "Dilnoza", "Feruza"},
"Dilnoza": {"Bobur", "Aziza"},
"Eldor": {"Aziz", "Feruza"},
"Feruza": {"Aziza", "Eldor"},
}
def umumiy_dostlar(a: str, b: str) -> set[str]:
return DOSTLAR[a] & DOSTLAR[b]
def tavsiya(kim: str) -> set[str]:
"""Do'stlarning do'stlari, o'zi va mavjud do'stlarsiz."""
natija = set()
for dost in DOSTLAR[kim]:
natija |= DOSTLAR[dost]
return natija - DOSTLAR[kim] - {kim}
print(f" Tarmoq:")
for kim in sorted(DOSTLAR):
print(f" {kim:<10} → {', '.join(sorted(DOSTLAR[kim]))}")
print(f"\n Umumiy do'stlar:")
for a, b in [("Aziz", "Dilnoza"), ("Aziz", "Feruza"), ("Bobur", "Eldor")]:
umumiy = umumiy_dostlar(a, b)
print(f" {a:<8} + {b:<8} → {sorted(umumiy) if umumiy else 'yo`q'}")
print(f"\n Tanish bo'lishi mumkin:")
for kim in sorted(DOSTLAR):
t = tavsiya(kim)
print(f" {kim:<10} → {', '.join(sorted(t)) if t else '—'}")
# Simmetriya tekshiruvi
print(f"\n Tarmoq simmetrikmi:")
xatolar = set()
for a, dostlari in DOSTLAR.items():
for b in dostlari:
if a not in DOSTLAR.get(b, set()):
xatolar.add((a, b))
print(f" {'✅ ha' if not xatolar else f'❌ {xatolar}'}")
print("\n\n=== 6. Tezlik: real vazifa ===")
N = 500_000
random.seed(7)
BAZA = [f"user{i}" for i in range(N)]
QIDIRUVLAR = [f"user{random.randrange(N * 2)}" for _ in range(10_000)]
boshlandi = time.perf_counter()
topildi_list = sum(1 for q in QIDIRUVLAR if q in BAZA[:5000])
vaqt_list = (time.perf_counter() - boshlandi) * 100
baza_set = set(BAZA)
boshlandi = time.perf_counter()
topildi_set = sum(1 for q in QIDIRUVLAR if q in baza_set)
vaqt_set = time.perf_counter() - boshlandi
print(f" {N:,} foydalanuvchi bazasi, {len(QIDIRUVLAR):,} ta qidiruv:\n")
print(f" list bilan: ~{vaqt_list * 1000:>9,.0f} ms")
print(f" set bilan: {vaqt_set * 1000:>9.1f} ms")
print(f" Tezlik: {vaqt_list / vaqt_set:>9,.0f}x")
print(f"\n Topildi: {topildi_set:,} / {len(QIDIRUVLAR):,}")Natijaning muhim qismi:
=== 2. Ruxsat tizimi ===
Foydalanuvchi Ruxsatlar Maqola yozish Izoh o'chirish
─────────────────────────────────────────────────────────────────────
Aziz 7 ✅ ✅
Bobur 6 ✅ ✅
Aziza 2 ❌ ❌
Mehmon 1 ❌ ❌
=== 5. Grafik: do'stlar tarmog'i ===
Umumiy do'stlar:
Aziz + Dilnoza → ['Aziza', 'Bobur']
Aziz + Feruza → ['Aziza', 'Eldor']
Bobur + Eldor → ['Aziz']
Tanish bo'lishi mumkin:
Aziz → Dilnoza, Feruza
Bobur → Aziza, EldorNima ko'rsatdi: 2.2, 2.4, 2.7-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
"{} — bo'sh to'plam" |
Lug'at. set() kerak |
| "To'plam saralangan" | Tartib yo'q. Kichik sonlar aldaydi |
| "To'plam tartibi barqaror" | Satrlar uchun har ishga tushirishda boshqa |
"set.pop() oxirgisini oladi" |
Tasodifiy element |
"in ro'yxatda ham tez" |
O(n) vs O(1) — millionlab marta farq |
| "To'plam har doim yaxshiroq" | 2-4x ko'p xotira; bir marta tekshiruvga isrof |
| "Har qanday obyekt qo'shiladi" | Faqat hashlanadigan |
"{1, True} — ikki element" |
Bitta: 1 == True |
"s.add([1,2]) ishlaydi" |
unhashable. update yoki tuple |
6. Keng tarqalgan xatolar va yechimlari
1. {} bilan bo'sh to'plam
s = {} # ❌ dict
s = set() # ✅2. Tartibga tayanish
birinchi = list(s)[0] # ❌ nomustaqil
birinchi = min(s) # ✅
birinchi = sorted(s)[0] # ✅3. Iteratsiya paytida o'zgartirish
for x in s:
s.remove(x) # ❌ RuntimeError
s = {x for x in s if not shart(x)} # ✅4. add o'rniga update
s.add([1, 2]) # ❌ unhashable
s.update([1, 2]) # ✅ ikki element
s.add((1, 2)) # ✅ bitta element5. remove — KeyError
s.remove(x) # ❌ yo'q bo'lsa xato
s.discard(x) # ✅6. Bir marta tekshirish uchun to'plam qurish
if x in set(katta_royxat): # ❌ O(n) qurish
if x in katta_royxat: # ✅
tekshirish = set(katta_royxat) # ✅ ko'p tekshiruv bo'lsa
for q in qidiruvlar:
if q in tekshirish: ...7. Takrorlarni olib tashlashda tartibni yo'qotish
noyob = list(set(royxat)) # ❌ tartib yo'qoladi
noyob = list(dict.fromkeys(royxat)) # ✅ tartib saqlanadi8. 1 va True aralashuvi
IDLAR | BAYROQLAR # ⚠️ True va 1 birlashadi
# Turlarni aralashtirmang, yoki:
{(type(x).__name__, x) for x in aralash}7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 6.8-dars: to'plam amallari —
|,&,-,^ - 6.9-dars:
frozenset— o'zgarmas to'plam - 6.10, 6.13-darslar:
dictva hash — bir xil tuzilma - 6.16-dars: to'plam generatorlari
{x for x in ...} - 6.5-dars (o'tilgan): tuple hashlanishi
- 8-qism:
__hash__va__eq__shartnomasi - 15-qism:
collections.Counter— sanash bilan
8. Eng yaxshi amaliyotlar
Bo'sh to'plam —
set().{}— lug'at.Ko'p marta
inkerak bo'lsa — to'plamga aylantiring. Bir marta uchun isrof.Tartibga hech qachon tayanmang. Kerak bo'lsa
sorted(s).Takrorsizlik + tartib =
dict.fromkeys().set()tartibni yo'qotadi.discard— xavfsiz o'chirish.removeKeyErrorberadi.Iteratsiya paytida o'zgartirmang. Yangi to'plam quring:
{x for x in s if ...}.Turlarni aralashtirmang.
1,1.0,True— bitta element.Testlarda to'plamni to'plam bilan solishtiring.
assert s == {"a"},list(s)emas.
9. Amaliy topshiriq
Vazifa 1: Natijani bashorat qiling
1. print(type({}))
2. print(type(set()))
3. print({1, 2, 2, 3})
4. print(set("hello"))
5. print({"hello"})
6. print({1, 1.0, True})
7. print({0, False, ""})
8. print(len({(1,2), (1,2), (2,1)}))
9. s = {1,2}; print(s.add(3))
10. print(set([1,2]) == {2,1})
11. print(set({"a": 1, "b": 2}))
12. print({1,2} == [1,2])Javoblar
<class 'dict'><class 'set'>{1, 2, 3}{'h', 'e', 'l', 'o'}— tartib turlicha{'hello'}— bitta element{1}— hammasi teng{0, ''}—0 == False, lekin"" != 02None—addjoyida o'zgartiradiTrue— tartib muhim emas{'a', 'b'}— kalitlarFalse— turlar farqli
Vazifa 2: Xatolarni tuzating
1. s = {}
2. birinchi = list(s)[0]
3. for x in s: s.remove(x)
4. s.add([1, 2])
5. s.remove(x) # x bo'lmasligi mumkin
6. noyob = list(set(royxat)) # tartib kerak
7. if x in set(katta_royxat): # bir marta
8. assert list(s) == ["a", "b"]Javoblar
1. s = set()
2. birinchi = min(s) # yoki sorted(s)[0]
3. s = {x for x in s if not shart(x)}
4. s.update([1, 2]) # yoki s.add((1, 2))
5. s.discard(x)
6. noyob = list(dict.fromkeys(royxat))
7. if x in katta_royxat:
8. assert s == {"a", "b"}Vazifa 3: Deduplikatsiya vositasi
Funksiyalar yozing:
noyob(it)— takrorsiz ro'yxat, tartib saqlangannoyob_kalit(it, key)— kalit funksiyasi bo'yichatakrorlar(it)— faqat takrorlangan elementlarbirmartaliklar(it)— faqat bir marta uchraganlarguruhlab_takrorlar(it, key)— takrorlanuvchi guruhlar
Har biri O(n) bo'lsin.
Vazifa 4: Matn tahlilchisi
Sinf yozing:
noyob_sozlar— to'plambir_martaliklar— hapax legomenaumumiy_sozlar(boshqa)— ikki matnda ham borfarqli_sozlar(boshqa)— faqat shu matndaoxshashlik(boshqa)— Jaccard indeksi- To'xtash so'zlari filtri (o'zbekcha)
- Apostrof normalizatsiyasi (4.8-dars)
Vazifa 5: Ruxsat tizimi
Kengaytiring (3-misol):
- Rollar iyerarxiyasi (
admin→moderator→foydalanuvchi) - Alohida ruxsat berish/olib tashlash
- Vaqtinchalik ruxsatlar (muddat bilan)
@ruxsat_kerak("maqola_yozish")dekoratori- Ruxsatlar auditi — kim nimaga ega
Vazifa 6: Tezlik tadqiqoti
Dastur yozing:
list,set,dict,sorted list + bisectuchunintezligi- Turli hajmlarda (10 → 1M) grafik
- To'plam qurish narxi qachon qoplanadi
- Xotira sarfi bilan solishtirish
frozensetbilan farq bormi
Vazifa 7: O'ylash
Nega set xotirada list dan 2-4x ko'p joy oladi, garchi u kamroq ma'lumot saqlasa ham (tartib yo'q, takror yo'q)?
Javob
Sabab: hash jadvali ataylab bo'sh joy qoldiradi.
1. Yuklanish koeffitsienti (load factor).
Hash jadvali to'lib qolsa, to'qnashuvlar ko'payadi va qidirish O(1) dan O(n) ga siljiy boshlaydi.
Yuklanish 50%: o'rtacha ~1.5 solishtirish
Yuklanish 66%: o'rtacha ~2 solishtirish
Yuklanish 90%: o'rtacha ~5.5 solishtirish
Yuklanish 99%: o'rtacha ~50 solishtirishCPython yuklanishni 3/5 (60%) dan past ushlab turadi. Ya'ni 100 element uchun ~167 uyacha kerak.
2. Har uyacha ko'proq joy oladi.
list uyachasi — 8 bayt (bitta ko'rsatkich).
set uyachasi (setentry) — 16 bayt:
typedef struct {
PyObject *key; // 8 bayt — element
Py_hash_t hash; // 8 bayt — KESH QILINGAN hash
} setentry;Hash keshlanadi, chunki:
- Jadval kattalashganda qayta hisoblash kerak emas
- Solishtirishdan oldin hash'larni tekshirish arzonroq
3. Jadval hajmi — 2 ning darajasi.
hash % hajm o'rniga hash & (hajm - 1) ishlatish uchun (bitli AND — bo'lishdan ~10x tez). Shuning uchun jadval 8, 16, 32, 64, 128... o'sadi.
100 element → keyingi mos hajm 256 uyacha (yuklanish 39%).
Hisob:
1000 element:
list: 56 + 8 × 1000 = 8,056 bayt
set: ~200 + 16 × 2048 = ~33,000 bayt (4.1x)4. Kichik to'plamlar uchun ichki massiv.
CPython set obyektida 8 ta uyacha ichkarida saqlanadi (smalltable). Shuning uchun bo'sh to'plam ham 216 bayt:
216 = obyekt sarlavhasi (~88) + 8 uyacha × 16 baytBu — kichik to'plamlar uchun qo'shimcha ajratishni oldini oladi.
Savdo tahlili:
list |
set |
|
|---|---|---|
| Xotira (1000 int) | 8 KB | 33 KB |
in (1000 element) |
~3.8 ms/1000 | ~0.05 ms/1000 |
76x tezlik uchun 4x xotira. Deyarli har doim foydali savdo.
Qachon foydali emas:
- Juda katta ma'lumot + kam tekshiruv (xotira chegarasi)
- Kichik to'plamlar (< 10 element —
listda ham tez) - Faqat bir marta o'tish kerak (generator yetarli)
Muqobil: saralangan list + bisect — O(log n) qidirish, list xotirasi bilan. Lekin qo'shish O(n).
Xulosa: to'plam xotirani ataylab isrof qiladi — bu uning tezligining asosi, kamchiligi emas. Bu — informatikadagi klassik "vaqt vs xotira" savdosi, va bu holda vaqt deyarli har doim qimmatroq.
Nimani mustahkamlaydi: 2.2, 2.3, 2.5, 2.7-bo'limlar.
Xulosa
Bu darsda to'plamning asoslarini o'rgandik.
Eng muhim uch fikr:
in— O(1). Bu to'plamning asosiy sababi. Hash jadvali element o'rnini bitta hisoblash bilan topadi, shuning uchun tekshirish elementlar soniga bog'liq emas. Millionlab elementli ro'yxatda bu 60 000x tezlik farqi.Tartib yo'q, takror yo'q, indeks yo'q.
{3, 1, 2}saralangandek ko'rinishi — kichik sonlar uchunhash(n) == nbo'lgani sabab tasodif. Satrlar uchun tartib har ishga tushirishda o'zgaradi.Elementlar hashlanishi kerak.
list,dict,set— hashlanmaydi.tuple,frozenset— hashlanadi. Va1,1.0,Truebitta element bo'lib qoladi.
Keyingi darsda to'plam amallari ni ko'ramiz: birlashma, kesishma, ayirma va simmetrik ayirma — hamda ular qanday qilib murakkab filtrlashni bir qatorga sig'diradi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!