Predavanje 12: Glava 32

FlipView[{Text[Style[" Branko Urošević, imqfbrankourosevic@gmail.com ",20,"Text",Italic]],Text[Style[" Faculty of Economics, University of Belgrade, NBS and CESIfo Munich",20,"Text", Italic]]}]

32. Prepoznavanje oblika (Pattern recognition)

Range[20]

Partition[Range[20],5]

Mean[{1,2,3,4,5,6}]

Mean/@Partition[Range[20],6,1]

Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,10},{j,10}],1]

RandomChoice[{a,b,c},10]

Table[RandomSample[{a,b,c},2],10]

?RandomSample

Uvod u prepoznavanje oblika

Ideja oblika (patterna) jeste da nađemo fundamentalnu strukturu nekog izraza. Oblici (patterns) su od ogromne važnosti u Wolfram Language. To su objekti koji predstavljaju cele klase izraza istovremeno. Prepoznavanje oblika (pattern matching) je proces pomoću koga se za neki izraz proveri da li odgovara (da li je match-ovan) sa nekim oblikom nekom šablonu ili formi. Zajedno sa Rule, možete ih koristiti da transformišete bilo koji izraz u oblik koji vas interesuje. Jedna od najvažnijih primena oblika jeste da se upravo pomoću njih definišu korisničke funkcije. Ali, o tome ćemo kasnije. Za sada samo želimo da ukapiramo šta su zapraavo obliki.

Blanko oblik (= bilo šta)

Funkcija MatchQ proverava da li neki izraz ima formu određeni oblik. Prvi argument jeste izraz koji proveravamo, a drugi argument jeste oblik (pattern) za koji hoćemo da ustanovimo da li matchuje po formi dati izraz. Ukoliko je odgovor potvrdan dobijamo True, a ako match nije ustanovljen dobijamo False.

Oblik _ (čitaj: "blanko") je oblik koji se match-uje sa bilo čim. Pošto blanko oblik pokriva sve moguće izraze koji se mogu napisati u WL, potpuno proizvoljni izrazi će Na primer, izraz Bob koji nije prethodno definisan je "nešto" pa prema tome biće match-ovan sa blank.

_

MatchQ[Bob,_]

MatchQ[Log[Bob]+suncica-15,_]

MatchQ["string se matchuje takođe",_]

Dakle, šta god da stavimo bilo šta kao prvi argument u MatchQ, to će biti matchovano oblikom _.

Ograničenje na oblik patterna: _Integer i _Real oblici

Često smo zainteresovani za pattern matching na osnovu tipa izraza. Na primer, možemo da proverimo da li je nešto Integer (ceo broj). MatchQ uzima objekat (broj 3.15) i pokušava da match njegovu Head (glavu) sa Integer.

MatchQ["baraba",Integer_]

MatchQ[3.15,Integer_]

MatchQ[3.15,_Real]

MatchQ[3.15,_Integer]

Naravno, dobili smo False pošto je odgovarajuća glava

Head[3.15]

Takođe,

MatchQ[3.15,_Real]

Još primera sa _Integer

MatchQ["3",abc_String]

MatchQ["3",_Integer]

Primetimo da je Head izraza “3” zapravo String.

Head["3"]

A šta bi matchovalo “3”

MatchQ["3",_String]

Proveriti koji od ovih izraza matchuje određeni oblik

Možemo sada da proverimo koliko od ovih izraza ima glavu Integer.

MatchQ[#,_Integer]&/@{21,"27",3+4I,2.15,3/5}

MatchQ[#,_Complex]&/@{21,"27",3+4I,2.15,3/5}

MatchQ[#,_Rational]&/@{21,"27",3+4I,2.15,3/5}

Vidimo da svaki od patterna tipa _Nešto matchuje samo one izraze koje koji imaju oblik (glavu) Nešto. Sa druge strane, ukoliko stavimo blanko, on matchuje svaki izraz pošto nismo stavili nikakvo ograničenje.

MatchQ[#,babaroga_]&/@{21,"27",3+4I,2.15,3/5}

Uvod u Cases

Cases[{2.13,3,-4,4.0,10},_Integer]

Funkcija Cases je moćna funkcija koja koristi oblike. Naime, ona izdvaja iz neke liste samo one elemente koji zadovoljavaju određenu formu odnosu matchuju određeni pattern. Pretpostavimo da želimo da iz liste elemenata izdvojimo samo cele brojeve koristeći Cases. Sintaksa je da prvo stavimo listu, a kao drugi argument stavimo odgovarajući oblik (pattern) koji želimo da matchujemo.

Evo primera:

Cases[{21,"27",3+4I,2.15,3/5},_Integer]

Cases je izdvojio samo element 21 pošto je samo taj element matchovan na oblikom _Intereger

MatchQ[#,_Integer]&/@{21,"27",3+4I,2.15,3/5}

Po istom principu, Cases će match-ovati sve elemente ukoliko pattern nema nikakvo ograničenje, to jest ukoliko je samo blank, _

Cases[{21,"27",3+4I,2.15},_]

Matchovanje malo apstraktnijeg oblika

Razmotrimo sledeću listu i pronađimo sve izraze koje imaju glavu g:

{g[x],f[x],g[h[x]],Sin[g[x]]}

Pošto Cases matchuje Head nekog izraza možemo da probamo i ovako nešto:

Cases[{g[x],f[x],g[h[x]],Sin[g[x]]},_g]

Proveriti na više načina to isto

To možemo proveriti na više načina. Jedan je da vidimo Head svakog od ovih izraza

Head[#]&/@{g[x],f[x],g[h[x]],Sin[g[x]]}

Drugi način bi bio da se za svaki član proveri da li je matchovan sa oblikom _g

MatchQ[#,_g]&/@{g[x],f[x],g[h[x]],Sin[g[x]]}

Primeri: matchovanje oblika _Plus, _String i _Times

U prethodnom primeru imali smo apstraknu glavu g koju smo želeli da matchujemo. Naravno, glava može bilo koja validna glava. Evo primera. Koji od ovih izraza ima glavu Plus?

Cases[{a+b,2+3,"3+4", a (b+c)},_Times]

Cases[{a+b,2+3,"3+4", a (b+c)},_Plus]

To možemo proveriti i ovako:

Head[#]&/@{a+b,2+3,"3+4", a (b+c)}

Primetimo da u slučaju aritmetričkih operacija na brojevima (kao što je 2+3), WL to odmah izračuna pre nego što Cases stigne da sa tim radi, pa je Head[2+3] =Integer pošto je to u stvari Head[5].

Primetimo da:

Cases[{a+b,2+3,"3+4", a (b+c)},_String]

Cases[{a+b,2+3,"3+4", a (b+c)},_Times]

Matching eksplicitnih oblika

DeleteCases[{10,30,31.3,"N/A","nema",4},_String]

Oblici koje smo do sada razmatrali su bile generalne klase izraza (bilo šta, ili samo određeni tip glave). Nekada je korisno matchovati eksplicitne izraze. Pretpostavimo da želimo da obrišemo sve nule u listi brojeva:

{10,-11.1,0,21,0,b}

DeleteCases radi kao Cases samo što briše one elemente koji su matchovani. U ovom slučaju nula je oblik koji treba da se matchuje:

DeleteCases[{10,-11.1,0,21,0,b},b]

DeleteCases[{10,-11.1,0,21,0,b},0]

To isto možemo da postignemo i korišćenjem Cases, ali je tada argument koji treba da matchujemo sve osim nule, odnosno Except[0]. Drugi rečima ovo ostavlja sve elemente osim nule:

Cases[{10,-11.1,0,21,0,b},Except[0]]

Matchovanje eksplicitnih oblika mora biti egzaktno

Evo interesatnog primera. Probajmo da obrišemo sve elemente liste koje su identično jednake celom broju 0.

Cases[{10,-11.1,0.,21,0,b},Except[0]]

Zašto smo je ostao 0. u listi? Razlog je, naravno, da je 0. zapravo realan a ne ceo broj pa nije matchovan.

0.===0

0.==0

MatchQ[#,Except[0]]&/@{10,-11.1,0.,21,0,b}

Još primera egzaknog matchovanja

Naravno, ne moramo matchovati samo cele brojeve egzaktno:

Cases[{10,-11.1,0.,21,0,b},b]

Cases[{10,-11.1,0.,21,0,b},Except[b]]

Cases[{10,-11.1,0.,21,0,b},Except[0.]]

Primetimo da smo sada matchovali (i izbacili) iz liste realni broj nula sa tačkom na kraju. Da li je to isto kao i?

Cases[{10,-11.1,0.,21,0,b},Except[0.0]]

Očito, jeste.

Strukturirani oblici: mathovanje proizvoljne subliste dimenzije 2

Patterni koje možemo da matchujemo mogu biti kompleksiji.  Pretpostavimo da želimo da ostavimo samo podliste koje sadrže tačno dva elementa (bilo koja) ali ne i podliste koje imaju 3 elementa. To postižemo oblikom {_,_} ili, u punom obliku, List[_, _]:

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{_,,_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{_,_,_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{1,prviipravi_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{prviipravi_,}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{prviipravi_,prviipravi_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{,},{,}},{baba_,baba_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,}},{baba_,zaba_}]

Cases[{{1,},{1,},{1,,},{2,,},{2,}},{_,_}]

što je isto što i

Head[]

Cases[{{1,},{1,},{1,,},{2,,},{2,}},List[_Integer,]]

{_,_}

Primetimo, naime da lista od tri elementa nema odgovarajući oblik

MatchQ[{1,,},List[_,_]]

dok ga lista od dva elementa ima

MatchQ[{1,},List[_,_]]

Imenovanje oblika

Kao što ćemo videti, veoma moćno sredstvo za rad sa oblicima jeste da ih imenujemo. Umesto da pišemo blanko oblike, možemo oba blanko oblika da zamenimo sa imenovanim blanko oblicima. Ukoliko želimo da matchuje oblike bez ograničenja sa njihove vrednosti onda izrazi koje koristimo za imenovanje moraju da se razlikuju (na primer, p i q). Ovo izdvaja subliste koje imaju tačno dva elementa (proizvoljna):

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},{p_,q_}]

što je isto što i

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},List[p_,q_]]

Primetimo da ime paterna može biti bilo koji validni izraz. Na primer, ovo će raditi potpuno isto:

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},List[lav_,lav_]]

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},List[tigar_,lav_]]

pitagora=Flatten[Table[{i,j,(Sqrt[(i^2)+(j^2)])},{i,1,30},{j,30}],1];

Cases[pitagora,{_,_,_Integer}]

Pravimo imenovanja

Primetimo da ime kod imenovanog oblika ide pre a ne posle blanka. Naime sova_ je proizvoljni imenovani oblik čije je IME sova dok je _sova oblik koji treba da matchuje one izraze koji imaju glavu sova. Evo primera

Cases[{a,sova[b],sova,c[sova]},sova_]

Primetimo da sova_ matchuje svaki izraz jer je to, zapravo, proizvoljni oblik samo što ima ime sova.  Sa druge strane:

Head[sova]

Cases[{a,sova[b],sova,c[sova]},_sova]

matchujemo samo izraze čija je glava sova. Primetimo da

Head[#]&/@{a,sova[b],sova,c[sova]}

Izdvojimo samo one podliste koje imaju dva ista elementa

Evo zašto je korisno imenovati oblike. Oblik liste dimenzije 2 u kojoj su oba elementa ista definišemo pomoću istog imenovanog oblika, recimo {p_,p_}. Evo primer:

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},{p_,p_}]

Primetimo da je to isto što i, na primer

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},{lav_,lav_}]

Izdvojimo podliste sa 3 elementa gde su 2. i 3. element isti

Evo još primera kako rade imenovani patterni. Pretpostavimo da želimo da nađemo sve podliste dimenzije 3 koje imaju poslednja dva elementa jednaka. U tom slučaju to možemo napisati ovako:

Cases[{{2,3},{3,3},{5,2}},{x_,y_}/;x+y≥ 6]

Cases[{{1,},{1,},{,},{5,5,5},{4,5,5},{,,},{1,},{1,,},{2,,},{2,},{,}},{lav_,tigar_, tigar_}]

Primetimo da je takvih podlisti samo jedna:

MatchQ[#,List[lav_,tigar_, tigar_]]&/@{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}}

ParametricPlot[{3 Cos[t],3 Sin[t]},{t,0,2 π}]

?Circle

Graphics[Circle[{0,0},{3,2}]]

ParametricPlot[{3 Cos[t],2 Sin[t]},{t,0,2 π}]

Oprez kada želimo da matchujemo algebarske izraze

Razmotrimo sledeću stvar. Pokušavamo da matchujemo izraze koji imaju brojilac i imenilac, odnosno oblik Divide[a_,b_] ili a_/b_

FullForm[a/b]

FullForm[((x/z)/(y+z))]

Cases[{2,9/3,1/3,(x/(y+z)),((x/z)/(y+z))},((a_)/(b_))]

Cases[{2,9/3,1/3,(x/(y+z))},((a_)/(b_))]

odnosno

Cases[{2,9/3,1/3,(x/(y+z))},Divide[a_,b_]]

Obratimo pažnju na FullForm. Ovo će nam dati ideju o čemu se radi.

FullForm[Divide[a,b]]

FullForm[#]&/@{2,9/3,1/3,(x/(y+z))}

Matchovanje Rational odnosno Divide

Primetimo da 1/3 nije matchovana sa Divide[a_,b_]

MatchQ[1/3,Divide[a_,b_]]

nego sa Rational[a_,b_]:

MatchQ[1/3,Rational[a_,b_]]

Kombinacija eksplicitnih i opštih oblika

Naći listu koja se sastoji od podlista dužine 2 čiji je prvi element 1. Oblik koji treba da matchujemo možemo napisati na više načina. Jedan je {1, _}. Dakle to je lista od dva elementa u kojoj je prvi element 1.

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},{1,_}]

To isto možemo napisati i pomoću imenovanog oblika ovako

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},List[1,sova_]]

Izdvojimo elemente koji se sastoje od podlisti dužine 2 i čiji je drugi element .

Cases[{{1,},{1,},{,},{,,},{1,},{1,,},{2,,},{2,},{,}},List[djoka_,]]

Alternative

U patternu možemo imati i alternative. Ukoliko nas interesuje izaberemo uređene parove čiji je prvi element ili 1 ili 2 to možemo da uradimo pomoću takozvane operacije alternative. Na primer, 1|2 jeste “ili 1ili 2”.

Naći listu takvu da prvi element može biti bilo 1 bilo 2.

Cases[{{1,},{1,},{1,,},{2,,},{2,}},{1|2,popadija_}]

Tu je drugi element liste proizvoljan. Naći elemente dimenzije 2 čiji je drugi element crvena ili plava boja:

Cases[{{1,},{1,},{1,},{,1},{1,,},{2,,},{2,}},{dekanat_,||}]

Eliminacija više različitih tipova elemenata iz liste:

DeleteCases[{"N/A",5,7,"NA",10},"N/A"|"NA"]

Izbaciti iz liste

{10,-11.1,0.,21,0,b}

kako 0 tako i 0.0

Cases[{10,-11.1,0.,21,0,b},Except[0.|0]]

ili, koristeći DeleteCases

DeleteCases[{10,-11.1,0.,21,0,b},0.|0]

Kako čistiti podatku u slučaju složenih lista?

Ako probamo da izbacimo na ovaj način iz složene liste 0 ili 0.0 to neće raditi. То је stoga što eksplicitni oblik pretpostavlja prostu listu kako bi mogao da matchuje konkretan element.

Cases[{{10,-11.1,0.,21,0,b},{0,3}},Except[0.|0]]

Ali, ako primenimo Cases na svaku od podlista, to će raditi

Cases[#,Except[0.|0]]&/@{{10,-11.1,0.,21,0,b},{0,3}}

Umesto da mapiramo Cases na podliste, možemo da specifikujemo nivo na koji Cases treba da deluje

Cases[{{10,-11.1,0.,21,0,b},{0,3}},Except[0.|0],{2}]

Ovde je opcija {2} na kraju odredila da idemo na dubinu 2. Ujedno, to je dovelo do toga da smo spljeskali strukturu liste.

Matchovanje sekvenci (Sequence matching)

Izraz sa dva blanka __ (“double blank”) matchuje jedan ili više elemenata u nekoj listi. Naravno, njih možemo takođe imenovati. Najbolje je da odmah na primeru vidimo kako to radi.  Kako da nađemo one podliste koje su proizvoljne dužine (za to nam treba dupli blank) a koji se završavaju sa Blue:

Cases[{{1,},{1,},{1,,},{2,,},{2,},{}},{zaba__,}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{}},{baba___,}]

Cases[{{,1,},{,1},{1,},{1,},{1,,},{2,,},{2,},{}},{1|,___}]

Cases[{{,1,},{,1},{1,},{1,},{1,,},{2,,},{2,},{}},{,___}]

Cases[{{1,},{1,},{1,,},{2,,},{2,},{}},{__,}]

To možemo predstaviti, razume se i nekako ovako:

Cases[{{1,},{1,},{1,,},{2,,},{2,}},List[babaroga__,]]

Vidimo da smo tu dobili sve elemente koji se završavaju sa . Sa druge strane, ukoliko bismo koristili samo jedan blank dobijamo samo one podliste koje se završavaju plavom bojom ali koje imaju dužinu 2:

Cases[{{1,},{1,},{1,,},{2,,},{2,}},{baba_,}]

Kombinacija alternativa i matchovanja sekvenci

Naći elemente koji počinju sa 1 ili 2, onda imaju bilo šta i, završavaju se sa  :

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},{1|2,__,}]

to je isto što i

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},List[1|2,popaj___,]]

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},List[1|2,popaj__,]]

Izabrati one podliste koje se završavaju na crvenu  boju, a imaju proizvoljan broj elemenata.

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},List[popaj__,]]

Izbrati elemente koji se završavaju sekvencom u kojoj posle crvene ide na kraju plava. Imaju proizvoljan broj elemenata.

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},List[popaj___,,,]]

Cases[{{1,},{1,},{1,,},{2,,},{2,,,},{2,}},List[popaj__,,]]

Flatten[{{{{3,2},{5,4,3}}}}]

Flatten[{{{{3,2},{5,4,3}}}},2]

Flatten[{{{3,2},{5,4,3}}},1]

FullForm[{{{{3,2},{5,4,3}}}}]

?Flatten

Flatten[List[f[List[1,2,3],List[4,3]]],1]

FullForm[List[f[{1,2,3},{4,3}]]]

Matchovanje apstraktnijih izraza pomoguću sekvenci odnosno double blank

Pretpostavimo da želimo da matchujemo bilo koji izraz koji ima Head f i koji ima jedan ili više argumenata. Jedan način da to uradimo jeste da kažemo nešto ovako:

Cases[{f[],g[,],{1,2,3},f[],f[3,4],f[]},f[___]]

Cases[{f[],g[,],{1,2,3},f[],f[3,4]},f[__]]

Cases[{1,a,b,10},strudlasamakom_Integer]

To isto možemo da predstavimo, razume se, i pomoću imenovanog oblika

Cases[{f[],g[,],{1,2,3},f[],f[3,4]},f[strudla__]]

Prepostavimo da želimo da matchujemo one izraze u kojima je Head jednak f i gde imamo samo jedan argument.

Cases[{f[],g[,],{1,2,3},f[],f[3,4]},f[_]]

Još o matchovanju listi

Probajmo ovo:

MatchQ[{a,b,c,d},{jedan_}]

Pošto je pattern lista od jednog elementa a mi imamo listu od četiri elementa, ovo daje False. Sa druge strane:

MatchQ[{},{vise___}]

MatchQ[{a,b,c,d},{vise___}]

MatchQ[{a,b,c,d},{vise__}]

pošto double blank odgovara bilo kakvoj listi od jednog ili više elemenata. Iz složene liste izdvojimo samo podliste koje imaju dimenziju 1.

Cases[{{a,b,c,d},{1},{2},{3,4}},{_}]

Matchovanje algebarskih izraza

Cases[{{1,2,3,4},{1,2,5,4},{2,3,4},{3,4},{4}},{_,_,_,_}|{_,_,_}]

Da probamo sada da nađemo koje su variable nešto dignuto na stepen (to se zove monom). Hteli bismo da kao output dobijamo prvi i drugi član. Međutim:

Cases[a (x^3)+b (x^2)+c x+d,(var_)^n_]

Razlog je da su neki od ovih izraza vrlo nested:

Cases[f[a (x^3)+b (x^2)+c x+d],(var_)^n_,3]

Cases[a (x^3)+b (x^2)+c x+d,(var_)^n_,2]

TreeForm[f[a (x^3)+b (x^2)+c x+d]]

FullForm[a (x^3)+b (x^2)+c x+d]

Stoga moramo da sa oblikom idemo duboko unutra. Jedan od načina da to uradimo jeste da idemo beskonačno duboko i tražimo maching:

Cases[a (x^3)+b (x^2)+c x+d,(var_)^n_,Infinity]

Korišćenje matchovanja oblika da menjamo izraze pomoću Replacement

Jedan od puno načina da se koriste oblici jesu zamene ili replacements. O njima ćemo veoma detaljno pričati u jednoj od narednih glava. Za sada primetimo da je replacement operator  /. (“slash dot”). Veoma je važan u WL.

Zamenite b sa Red u listi:

(x^2)+(y^2)/.{x-> 50,y-> 60}

{a,b,a,a,b,b,a,b}/.{b->Red,a-> Blue}/.{-> 1000,-> 2000}

a

{a,b,a,a,b,b,a,b}/.b->Red

Zamenite sve podliste od 2 elementa koji počinju sa 1 sa simbolom x. Kako to radi: pattern prvo pronalazi šta treba da se zameni. Onda se sve što treba da se zameni - zameni.

{{1,},{1,},{1,,},{2,,},{2,}}/.{1,_}->x

{{1,},{1,},{,},{,},{1,,},{2,,},{2,}}/.{ista_,ista_}->  {ista,ista,ista}

{{1,},{1,},{,},{,},{1,,},{2,,},{2,}}/.{ista_,ista_}:>  {ista,ista,ista}

Lista pravila za zamenu

Možete da imate i listu pravila za zamenu. Ovde imamo listu od dva pravila zamene. Prvo pravilo je da kada imamo podlistu dužine 2 i prvi njen element počinje sa 1 zamenjujemo to podsiltu sa simbolom x. Drugo pravilo kaže da ako imamo podlistu proizvoljne dužine koja se završava sa Blue, zamenjujemo je sa y.

{{1,},{1,},{1,,},{2,,},{2,}}/.{{1,prvo_}->x,{drugo__,Blue}-> y}

Pretpostavimo da želimo da podliste dužine 2 koja ima iste elemente zamenimo sa z. Primetimo da takvih podlista ima dve

Cases[{{1,},{1,},{,},{,},{1,,},{2,,},{2,}},{ista_,ista_}]

a ovako bismo obavili tu zamenu

{{1,},{1,},{,},{,},{1,,},{2,,},{2,}}/.{ista_,ista_}-> z

Složenija upotreba imenovanog oblika

Imenovani patterni su posebno korisni za zamene (replacement). Na primer, nadjemo sve podliste koje imaju dužinu dva i čiji je prvi element 1, pa ih zamenimo na sledeći način:

{{1,},{1,},{1,,},{2,,},{2,}}/.{1,x_}->{x,x,x,Brown}

Naime, umesto te liste dužine dva, imaćemo listu u kojoj će prva tri elementa biti ponovljeni drugi element originalne podliste, a poslednji element će biti Brown. Operacija a->b je isto što i Rule[a,b]. Ako se x_ pojavljuje na levoj strani Rule, onda se na njega može pozivati sa desne strane Rule kao x.

Koristite x sa desne strane Rule da definišemo šta to matchuje  x_:

{f[1],g[2],f[2],f[6],g[3]}/.f[x_]->x+10

Rule može da se koristi i kod Cases. Ovde prvo nalazimo one elemente koje matchuju oblik f[x_], a onda zamenjujemo svuda x sa x+10:

Cases[{f[1],g[2],f[2],f[6],g[3]},f[x_]->x+10]

Korišćenje pravila za lokalno izračunavanje vrednosti izraza

Jedan od najčešćih primena Rule je da izračunamo vrednost nekog izraza lokalno (u nekoj konkretnoj liniji koda ali ne i globalno)

x^2+y^3/.{x-> 2,y-> 3}

x^2+y^3

parovi=RandomInteger[{-10,10},{20,2}]

parovi

Cases[parovi,{x_,y_}/;And[(x^2)+(y^2)≥ 50,x+y≥15]]

Cases[parovi,{x_,y_}/;(x^2)+(y^2)≥ 50]

Cases[parovi,{x_,y_}/;x+y==0]

Cases[parovi,{x_,y_}/;x>3]

Cases[parovi,{x_,y_}/;y<5]

pitagora=Flatten[Table[{i,j},{i,20},{j,20}],1];

Cases[pitagora,{x_,y_}/;And[IntegerQ[(Sqrt[(x^2)+(y^2)])],x≤ y]]

Cases[{{3,4,5,6},{3,1,6,3,4},{2,3},{3,1,0}},baba:{___}/;Total[baba]≥10]

Cases[{{3,4,5,6},{3,1,6,3,4},{2,3},{3,1,0}},x:{___}/;Length[x]==4]

Q and A

Da li važno kako ćemo nazvati neki pattern (x_ itd)?
Ne. Samo moraju da se konsistentno ta ime koriste. 

Šta još mogu biti patterni?
To ćemo diskutovati kasnije, u poglavlju 41.

Kakva je razlika između | i ||?
p|q je alternativa vezana za pattern, a p||q is a logic construct, that tests whether p or q is True.

Kako se  /. interpretira?
To je funkcija ReplaceAll. Replace pokušava da zameni odgovarajuče patterne u celom izrazu. ReplaceList daje listu rezultata svih mogućih načina da se matchuje neki pattern. 

Ako /. ima više replacementa, koji će koristiti?
Koristi prvu na koju naiđe. Ako replacements mogu da se naprave na raznim nivoima izraza, /. pravi zamenu na najmanjem nivou (koji je najviše spolja).

Tehnički komentari
Patterns za stringove ćemo diskutovati u odeljku 42.

Pattern matching u Wolfram Language uzima u obzir ekvivalenciju izraza kao što x+y i y+x, ili x+(y+z) i (x+y)+z.

Kada pišemo lhs->rhs, lhs je “left-hand side” a rhs je “right-hand side”.