Shanraq.org Shanraq.org
Жиындар: `&`, `-`, `|` және екінші выгрузкада жоқ нәрсе
IT

Python: деректен өз есебіңізге дейін 15-сабақ (барлығы 56)

Жиындар: `&`, `-`, `|` және екінші выгрузкада жоқ нәрсе

Python курсының он бесінші сабағы. Тізімдегі бес атаудың әртүрлісі — төртеу: жиын қайталауды үнсіз жеп қояды. Оның есесіне екі деректер экспортына қойылған үш сұрақ үш таңбамен шешіледі: `&` — екеуінде де не бар, `-` — не қалмаған, `|` — бәрі бірге. Плюс `{}` — бос жиын емес, бос сөздік.

Не үшін керек

Тізімдер мен сөздіктер «нешеу» және «осы кілт бойынша не бар» деген сұрақтарға жауап береді. Деректермен жұмыста бәрінен жиі қойылатын үшінші сұрақ бар: бар ма, жоқ па.

Екі деректер экспорты келді — қаңтар мен ақпан. Екеуінде де не болды? Екіншісінде не қалмады? Не жаңа пайда болды? Тізіммен мұны кірістірілген циклмен санайды, әрі онда қателесу оңай.

Жиын — қайталаусыз және ретсіз жинақ. «Бар ма, жоқ па» үшін керегінің дәл өзі, әрі екі деректер экспортына қойылған үш сұрақты ол үш таңбамен шешеді.

Бірден тұтас

jiyn.py файлы. Іске қосу: ортадан python jiyn.py.

Міндеттісі — алғашқы екі блок: тізімді жиынға айналдыру және үш амал. Үшінші мен төртіншісі орнында тексеруді және екі тұзақты көрсетеді.

"""15-сабақ: жиын — «бар ма, жоқ па» туралы, «нешеу және қай ретпен» туралы емес.

Әр айдағы екі тауар деректер экспорты. Оларға қойылатын сұрақ бірдей: екеуінде де не
бар, екіншісінде не қалмаған, не жаңа пайда болған. Тізіммен мұны циклмен
санайды, жиынмен — бір таңбамен.
"""

january = ["нан", "сүт", "май", "тұз", "нан"]
february = ["нан", "сүт", "қант", "жұмыртқа"]

print("== жиынға айналдырғанда не жоғалады")
a = set(january)
b = set(february)
print("қаңтар тізімінде:", len(january), "| әртүрлі атау:", len(a))
print("жиынды сұрыпталған күйде басады:", sorted(a))

print()
print("== үш сұрақ — үш таңба")
print("екеуінде де бар (a & b):   ", sorted(a & b))
print("екіншісінде жоқ (a - b):   ", sorted(a - b))
print("пайда болды (b - a):       ", sorted(b - a))
print("бәрі бірге (a | b):        ", sorted(a | b))
print("тек біреуінде (a ^ b):     ", sorted(a ^ b))

print()
print("== бар ма, жоқ па, әрі ішіне кіре ме")
print("«тұз» қаңтарда:", "тұз" in a, "| ақпанда:", "тұз" in b)
print("ақпан қаңтардың ішінде:", b <= a, "| қиылысады:", not a.isdisjoint(b))
print("екі айда барлығы неше түрлі:", len(a | b))

print()
print("== екі тұзақ")
print("{} типі —", type({}).__name__, "| set() типі —", type(set()).__name__)
try:
    {["нан", "сүт"]}
except TypeError as error:
    print("тізімді ішіне салуға болмайды:", error)

Шығатыны:

== жиынға айналдырғанда не жоғалады
қаңтар тізімінде: 5 | әртүрлі атау: 4
жиынды сұрыпталған күйде басады: ['май', 'нан', 'сүт', 'тұз']

== үш сұрақ — үш таңба
екеуінде де бар (a & b):    ['нан', 'сүт']
екіншісінде жоқ (a - b):    ['май', 'тұз']
пайда болды (b - a):        ['жұмыртқа', 'қант']
бәрі бірге (a | b):         ['жұмыртқа', 'май', 'нан', 'сүт', 'тұз', 'қант']
тек біреуінде (a ^ b):      ['жұмыртқа', 'май', 'тұз', 'қант']

== бар ма, жоқ па, әрі ішіне кіре ме
«тұз» қаңтарда: True | ақпанда: False
ақпан қаңтардың ішінде: False | қиылысады: True
екі айда барлығы неше түрлі: 6

== екі тұзақ
{} типі — dict | set() типі — set
тізімді ішіне салуға болмайды: cannot use 'list' as a set element (unhashable type: 'list')

Талдау

Қайталаулар үнсіз жоғалады

қаңтар тізімінде: 5 | әртүрлі атау: 4

set(january) екінші «нанды» ештеңе демей лақтырып тастайды. Жиынның басты қасиеті осы: элемент не бар, не жоқ, ал ол неше рет кездескені — оған қойылатын сұрақ емес.

Осыдан ең жиі кездесетін адал қолданысы шығады: деректе неше әртүрлі мән бар екенін санау. len(set(...)) мен len(...) — бір жол, әрі деректер экспортында дубликат бар-жоғы бірден көрінеді.

Осыдан қате де шығады: қайталау дерек болып тұрған жерде жиынды алуға болмайды. Айына үш рет нан сатып алу — бұл үш сатып алу, біреу емес; ол үшін жиын емес, тізім не санауыш керек.

Елестетіп көріңіз. Шақырылғандар тізімі. Онда кімнің шақырылғаны маңызды, оны неше рет жазғаны емес. Ал бұл сатып алу тізімі болса, екі нан — бұл екі нан.

Реті жоқ, сондықтан sorted арқылы басады

print("жиынды сұрыпталған күйде басады:", sorted(a))

Жиында рет жоқ — қосқан реті де, басқасы да. Оны тікелей басып шығарыңыз, әрі рет басқа машинада немесе басқа іске қосуда өзгеше болуы мүмкін: ол элементтердің іште қалай орналасқанына тәуелді.

Сондықтан ереже қарапайым: жиынды sorted арқылы көрсетеді. Сонда шығу бәрінде бірдей болады, әрі оны көзбен салыстыруға келеді. Бағдарламаның ішінде рет керек емес — онда жиыннан сұрайды, оны оқымайды.

Үш сұрақ — үш таңба

екеуінде де бар (a & b):    ['нан', 'сүт']
екіншісінде жоқ (a - b):    ['май', 'тұз']
пайда болды (b - a):        ['жұмыртқа', 'қант']

& — қиылысу: екеуінде де не бар. - — айырма: біріншісінде бар, екіншісінде жоқ. | — бірігу: бәрі бірге, әрқайсысы бір реттен. ^ — симметриялы айырма: тек екеуінің біреуінде ғана бар нәрсе.

- таңбасында рет маңызды: a - b пен b - a әртүрлі сұраққа жауап береді — «не қалмады» және «не пайда болды». Бұл — бастапқыда ең жиі шатасатын жер, әрі ол дауыстап қойылған сұрақпен емделеді: қай жиыннан азайтып тұрмыз.

Барлық таңбаның сөзбен жазылған сыңары бар: a.intersection(b), a.difference(b), a.union(b), a.symmetric_difference(b). Таңба қысқа, сөз бөтен кодта түсініктірек — сол жерде қайсысы жақсы оқылса, соны алады.

«Бар ма, жоқ па» — жиындар сол үшін ойлап табылған

"тұз" in a

in тексеруі тізіммен де, жиынмен де жұмыс істейді, бірақ әртүрлі. Тізімде Python элементтерді тапқанша аралайды: тізім неғұрлым ұзын болса, соғұрлым ұзақ. Жиында ол элемент қай жерде жатуға тиіс екенін бірден есептейді де, тек сол жерге қарайды — ұзындықтың мәні жоқ.

Он жолда айырма байқалмайды. Циклмен тексерілетін жүз мың жолдық деректер экспортында бұл — «бір секунд» пен «жарты сағаттың» айырмасы, әрі жиынды кейде тек тексеру үшін бастаудың жалғыз себебі де сол.

Қасында тұтас жинақ туралы сұрақтар тұр: b <= ab-ның барлық элементі a-да бар ма; a.isdisjoint(b) — олар мүлде қиылыспай ма.

Екі тұзақ

{} типі — dict | set() типі — set

Жүйелі жақшаны сөздік алып қойған: {} — бұл бос сөздік, бос жиын емес. Бос жиын — тек set(). Қате бірден көрінбейді: seen = {} бірінші seen.add(...) жолына дейін жұмыс істейді де, сол жерде сөздікте add жоқ дейді.

тізімді ішіне салуға болмайды: cannot use 'list' as a set element (unhashable type: 'list')

Жиынға өзгертуге келмейтін нәрсені ғана салуға болады: сандар, жолдар, кортеждер. Тізім өзгермелі — демек, оны ішіне салып, орны бойынша қойылған элементті өзгертуге болар еді, сонда жиын өзін-өзі таппай қалар еді.

Себебі сөздіктің кілті тізім болмайтын себеппен бірдей: екі жерде де элемент хеш бойынша орналастырылады. Өзгермейтін жинақ керек болса — frozenset бар, әрі оны басқа жиынның ішіне салуға болады.

Сабақ картасы

Сабақ картасы: қайталаулар, үш таңба және «бар ма, жоқ па»

Өз сөзіңізбен айтыңыз

Қарамай, дауыстап немесе қағазға жауап беріңіз. Жауаптары — сабақтың соңында.

  1. Жиын қайталаулармен не істейді, әрі бұл қашан зиянды?
  2. Екі деректер экспортында a - b b - a-дан немен өзгеше?
  3. Жиынды неге sorted арқылы басып шығарады?

Жаттығу

Тапсырмаға дейінгі үш қысқа қадам: болжау, толықтыру, жөндеу. Жауаптары — сабақтың соңында, бірақ алдымен өзіңіз жауап беріңіз.

1. Болжаңыз. Бұл жол не басып шығарады?

print(len([1, 2, 2, 3]), len({1, 2, 2, 3}))

2. Бос орынды толтырыңыз. ... орнына екінші деректер экспортында жоқ атауларды қалдыратын нәрсені қойыңыз.

a = {"нан", "сүт", "тұз"}
b = {"нан", "сүт", "қант"}
print(sorted(...))

3. Жөндеңіз. Бағдарлама екінші жолда құлайды. Қатені оқып, шынымен керегін жасаңыз.

seen = {}
seen.add("нан")
print(sorted(seen))

Тапсырма

Міндетті. Берілгені:

january = ["нан", "сүт", "май", "тұз", "нан", "жұмыртқа"]
february = ["нан", "сүт", "қант", "жұмыртқа", "жұмыртқа"]

Әр ай бойынша неше позиция болғанын және олардың ішінде нешеуі әртүрлі екенін басып шығарыңыз. Содан кейін үш жауап: екінші айда не қалмағанын, не жаңа пайда болғанын, екеуінде де не қалғанын. Соңында — екі айда барлығы неше әртүрлі атау бар екенін. Барлық жинақты sorted арқылы басыңыз.

Күтілетін шығу:

қаңтар: позиция 6 | әртүрлі 5
ақпан:  позиция 5 | әртүрлі 4
екіншісінде жоқ: ['май', 'тұз']
екіншісінде пайда болды: ['қант']
екеуінде де қалды: ['жұмыртқа', 'нан', 'сүт']
екі айда барлығы әртүрлі: 6

Дайын болғаны: шығу жол-жолмен сәйкес келеді; бірде-бір кірістірілген цикл жоқ — үш жауап та таңбамен алынған; әр жиын тікелей емес, sorted арқылы басылған.

Өз деректеріңізде. Өзіңіздің екі тізіміңізді алыңыз — екі чектегі тауарлар, екі чаттағы қатысушылар, екі қалтадағы файлдар. Сол үш сұраққа жауап беріңіз де, олардың қайсысы өміріңізде жиірек керек болатынын дауыстап айтыңыз.

Қалауыңызша.

  • Жиынды sorted-сіз бірнеше рет қатарынан басып шығарып, ретіне қараңыз.
  • Бірінші айдан frozenset жинап, оны басқа жиынның ішіне салыңыз.
  • Әр атаудың неше рет кездескенін санаңыз да, мұнда жиын неге жарамайтынын түсіндіріңіз.

Жобада бұл қайда тұрады

Шолу жоғалуларды байқай бастайды. Бұрын ол келгенін санайтын; енді өткенімен салыстырғанда жаңа деректер экспортында не жоқ екенін айта алады — ал бұл әлемнің емес, дереккөздің сынғанының алғашқы белгісі.

Қарыздар. Жиын «бар ма, жоқ па» дегенге жауап береді, «неше рет» дегенге емес — ол үшін санауыш керек, әрі ол collections модулі туралы сабақта пайда болады. Ретті де сақтамайды, сондықтан «алғашқы бес жаңасын» одан сұрыптаусыз алу мүмкін емес.

Жауаптар

Жауаптарды көрсету

Сұрақтарға

  1. Оларды үнсіз лақтырып тастайды: элемент не бар, не жоқ. Қайталау дерек болып тұрған жерде бұл зиянды: үш рет алынған нан біреу болып қалады да, чектің сомасы дұрыс шықпайды.
  2. a - b — екінші деректер экспортында не қалмағаны, b - a — онда не пайда болғаны. Сұрақтар әртүрлі, әрі қайсысына жауап бергеніңізді азайту реті шешеді.
  3. Өйткені жиынның өз реті жоқ: тікелей шығу басқа машинада не басқа іске қосуда өзгеше болуы мүмкін. sorted шығуды бәріне бірдей етеді.

Жаттығуға

  1. 4 3. Тізімде төрт элемент, жиында — үшеу: екінші екілік онда жоқ, әрі бұл туралы ешкім хабарламады.
4 3
  1. a - b. Осы реттегі айырма бірінші жинақта бар, екіншісінде жоқ нәрсені қалдырады.
a = {"нан", "сүт", "тұз"}
b = {"нан", "сүт", "қант"}
print(sorted(a - b))
['тұз']
  1. {} — бос жиын емес, бос сөздік, сондықтан онда add табылмады: AttributeError: 'dict' object has no attribute 'add'. Бос жиынды set() арқылы жасайды.
seen = set()
seen.add("нан")
print(sorted(seen))
['нан']

Дереккөздер

Мәтінде қате не теру қатесі кездессе, бізге айтыңыз

Тапсырманы тексеру

Алдымен VS Code-та шешіп, іске қосыңыз — редактор қатені сол жерде көрсетеді. Дайын шешімді осында қойыңыз. Тексеретін — модель: ол қатені атап көрсетеді, бірақ дайын жауапты бермейді.

Тексеру үшін кіру керек. Кіру

Пікірлер (0)

Әзірге пікір жоқ. Бірінші болыңыз.