Lekce 11 - Porovnávání textových řetězců v PHP II. část
V minulé lekci, Porovnávání textových řetězců v PHP, jsme se dozvěděli, jak porovnávat textové řetězce v PHP.
V tomto díle funkcí v PHP pro porovnávání textových řetězců si vysvětlíme užitečné funkce pro porovnávání. Některé funkce jsou sice méně známé, avšak je dobré se s nimi seznámit
strnatcmp()
Je funkce podobná funkci strcmp()
, o které jsme se bavili v
předchozím díle. Funkce strnatcmp()
porovná dva textové
řetězce. Pokud je první textový řetězec menší než druhý, vrátí
hodnotu menší než 0. Hodnotu větší než
0 vrací v případě, kdy je první řetězec větší než druhý.
Jsou-li oba řetězce identické, funkce vrátí 0. Funkce
porovnává textové řetězce pomocí tzv. přirozeného algoritmu (Natural
algorithm). V přirozeném algoritmu porovnávání je například číslo
5 menší než číslo 10, což zcela jistě
víme a nemusíme to dokazovat. V počítačovém řadícím algoritmu
(computer sorting) jsou pravidla pro řazení trochu odlišná,
například číslo 3 by bylo v tomto algoritmu řazení větší než číslo
20. je tomu tak, protože jsou porovnávána první začáteční čísla (resp.
3 a 20). Funkce strnatcmp()
je
case-sensitive tedy záleží na velkých a malých písmenech.
Funkce přijímá 2 parametry, kterými jsou textové řetězce k
porovnání:
$strnatcmp = strnatcmp('5', '10'); print_r($strnatcmp);
Zde porovnáváme čísla zapsaná v textových řetězcích. Jelikož je
první řetězec menší než ten druhý, výstupem na stránku pomocí funkce
pro výpis print_r()
bude -1. Funkce
strnatcmp()
dokáže také porovnávat desetinná čísla zapsané
jako textový řetězec:
$strnatcmp = strnatcmp('50', '49.999'); print_r($strnatcmp);
Výstupem na stránku bude číslo 1
, jelikož první řetězec
je větší než ten druhý. Další příklad:
$strnatcmp = strnatcmp('Stejný text', 'Stejný text'); print_r($strnatcmp);
Pokud jsou zadané textové řetězce totožné i velikostmi znaků, funkce vrátí 0:
$strnatcmp = strnatcmp('stejný text', 'Stejný text'); print_r($strnatcmp);
Avšak změníme-li velikosti znaků, dostaneme hodnotu v závislosti na velikosti řetězců, v tomto případě dostaneme číslo 1, tedy první textový řetězec je větší než ten druhý. Písmeno s má totiž v ASCII tabulce větší hodnotu než písmeno S.
$strnatcmp = strnatcmp('Alexandr', 'Božena'); print_r($strnatcmp);
V tomto případě vrátí funkce hodnotu -1, jelikož oba textové řetězce jsou odlišné a první znak v prvním řetězci je menší než znak ve druhém řetězci.
similar_text()
Funkce similar_text()
porovná dva textové řetězce a
vypočítá jejich podobnost (similaritu) na počet znaků s možností
přepočtu na procenta. Tato funkce je oproti funkci levenshtein()
,
kterou si ukážeme dále, pomalá, její časová komplexita je
O(N3). Avšak nabídne nám mnohem přesnější výsledek s malým
množstvím nutných úprav pro její implementaci. Funkce vrací počet
shodných znaků obou textových řetězců. Funkce similar_text()
je case-sensitive. Funkce přijímá 3 parametry, kde první
dva jsou textové řetězce k porovnání a posledním parametrem je
procentuální vyjádření podobnosti obou řetězců. Ukažme si
příklady:
$similar_text = similar_text('Pavel', 'Pavlína'); print_r($similar_text);
Funkce vrátí počet shodných znaků, avšak nezáleží na pořadí.
Výstupem funkce bude číslo 4, jelikož právě 4 znaky v
obou řetězcích jsou shodné. Jde o znaky P
, a
,
v
, a l
. Další příklad:
$similar_text = similar_text('Allljaska', 'Aljaska'); print_r($similar_text);
I přesto, že v prvním textovém řetězci máme více stejných znaků, než v řetězci druhém, je výstupem funkce číslo 7. Tedy počet shodných znaků v obou řetězcích. Pokud se nám opakuje jeden znak vícekrát, bude započítán pouze jednou (první výskyt).
$similar_text = similar_text('', '', $procenta); printf("Počet stejných znaků: %d <br/> Procentuálně: %f%%", $similar_text, $procenta);
Chceme-li si vyjádřit similaritu procentuálně u obou řetězců,
vložíme novou proměnnou (s názvem např. $procenta
) do
třetího parametru funkce. Pokud máme oba textové řetězce ve funkci
prázdné, dostaneme znakovou podobnost 0, procentuálně tedy
0%.
Používání této funkce může vyvolat také neočekávaný výsledek! Pokud bychom prohodili pořadí řetězců, tedy první řetězec namísto druhého, dostaneme zcela odlišný výstup funkce. Příklad:
$prvni = "bafoobar"; $druhy = "barfoo"; $similar_text = similar_text($prvni, $druhy); print_r($similar_text); $similar_text_2 = similar_text($druhy, $prvni); print_r($similar_text_2);
V prvním výpisu dostaneme znakovou podobnost 5, tedy přesně pět znaků je shodných. V druhém případě dostaneme podobnost 3, což neodpovídá počtu shodných znaků obou řetězců!
levenshtein()
Funkce levenshtein()
slouží pro porovnávání dvou textových
řetězců a vypočítá jejich odlišnou distanci, tedy hodnotu, o kolik znaků
se liší. Funkce přijímá celkem 5 parametrů, kde první dva jsou textové
řetězce k porovnání. Třetím, čtvrtým a pátým parametrem je číslo, o
kolik se bude zvětšovat distance v případě znaku v řetězci navíc,
výměnou znaku a odstraněním znaku (defaultní hodnota je 1
).
Pokud se stane, že jeden z řetězců přesáhne délku znaků
255, je výstupem funkce hodnota -1. Časová
komplexita je O(m×n), což je oproti funkci similar_text()
znatelně lepší. Ukažme si příklady:
$levenshtein = levenshtein('Text', 'text'); print_r($levenshtein);
Výstupem funkce je hodnota 1, tedy přesně o 1 znak je první nebo druhý textový řetězec rozdílný. Další příklad:
$levenshtein = levenshtein('Text', 'Text'); print_r($levenshtein);
Zde je návratová hodnota funkce rovna 0. To znamená, že oba řetězce si jsou rovny. Ještě jeden příklad:
$levenshtein = levenshtein('Ada Lovelace', 'Lovelace', 10, 15, 20); print_r($levenshtein);
Pokud uvedeme třetí, čtvrtý a pátý parametr, upravíme tím počítání rozdílů textových řetězců. V tomto případě je počet chybějících znaků v porovnání obou řetězců celkem 4. Avšak výstupem funkce bude číslo 80 (4×20), jelikož posledním parametrem upravujeme hodnotu pro chybějící (odstraněné) znaky, chcete-li "cenu za chybějící znak".
strcoll()
Funkce porovná dva textové řetězce stejně jako předchozí funkce.
Funkce strcoll()
porovná dva textové řetězce a pokud je první
textový řetězec menší než druhý, vrátí hodnotu menší než
0. Hodnotu větší než 0 vrací v případě, kdy je
první řetězec větší než druhý. Jsou-li oba řetězce identické, funkce
vrátí 0. Funkce je case-sensitive a
není binary-safe. Návratová hodnota funkce je ovlivněna
nastavenou lokací (znak (A) < (a) nebo (A) >
(a)). Ukažme si nějaké příklady:
$strcoll = strcoll('Edward Brown', 'Edwin Brown'); print_r($strcoll);
Funkce vrátí hodnotu -1, jelikož je první řetězec menší než ten druhý. Další příklad:
$strcoll = strcoll('brown', 'Brown'); print_r($strcoll);
Funkce vrátí hodnotu 1, jelikož je první řetězec
větší než ten druhý. Neboli, b < B
. Když zadáme stejné
řetězce:
$strcoll = strcoll('Edward', 'Edward'); print_r($strcoll);
funkce vrátí hodnotu 0. To taktéž platí u porovnávání dvou prázdných textových řetězců:
$strcoll = strcoll('', ''); print_r($strcoll);
substr_compare()
Funkce substr_compare()
porovná dva textové řetězce od
zadané pozice. Funkce vrátí kladné celé číslo, jestliže
první řetězec bude větší než ten druhý. Pokud vrátí záporné
celé číslo, je první řetězec menší než ten druhý. Řetězce
jsou totožné právě tehdy, kdy funkce vrátí hodnotu rovno
0. Přijímá celkem pět parametrů a první dva parametry jsou
textové řetězce k porovnání. Porovnává se vždy první s druhým.
Třetím parametrem je pozice začátku porovnávání, která je vyžadována
(required). Čtvrtým parametrem je nová délka, která určí, kolik
znaků budeme celkem porovnávat (defaultně celý textový řetězec). Na
rozdíl od ostatních funkcí zde můžeme specifikovat, zda bude brán zřetel
na velikosti písmen. Specifikujeme to posledním parametrem a ukážeme si to
níže na příkladech:
print_r(substr_compare("Půjdu brzy spát", "Půjdu brzy spát", 0));
Jelikož jsou dva textové řetězce totožné, dostaneme na výstup hodnotu
0
. Nesmíme ale zapomenout specifikovat třetí parametr!
Další:
print_r(substr_compare("Půjdu brzy spát", "Zítra brzy vstávám", 6));
Výstup funkce bude hodnota -1
, jelikož první řetězec je
menší než ten druhý. Třetím parametrem jsme zvolili začátek
porovnávání u prvního řetězce, bude tedy porovnáváno:
"brzy spát"
a "Půjdu brzy spát"
. Ukažme si další
příklad spolu s 4. parametrem:
print_r(substr_compare("Dnes jdu brzy do postele", "Dnes", 0, 8));
Použitím čtvrtého parametru jsme první řetězec zkrátili na
8 znaků
od pozice 0
ve třetím parametru. Jsou tedy
porovnávány řetězce: "Dnes jdu"
a "Dnes"
. První
řetězec je větší než ten druhý přesně o 4 znaky. Na výstupu dostaneme
tedy hodnotu 4
. Další příklad:
print_r(substr_compare("Dnes nebo jindy, na tom nesejde.", "JINDY", 10, 13, true));
Zde je opět porovnávána pouze část prvního řetězce, tedy od
počáteční pozice 10
a délky řetězce 13 znaků
(od počáteční pozice!). Poslední parametr s booleanovskou hodnotou
true
nám určuje, zda bude brán zřetel na velikosti písmen.
Pokud je hodnota pátého parametru true
je funkce
case-insensitive. Pokud je false
, tak
case-sensitive (záleží na velikosti). Porovnáváme tedy
řetězce: "jindy, na tom"
a "JINDY"
. První textový
řetězec je tedy o 8 znaků
větší, na výstupu dostaneme
hodnotu 8
.
Pokud do čtvrtého parametru zadáme délku prvního
řetězce nulovou, dostaneme na výstup hodnotu 0
. Pokud zadáme do
třetího parametru zápornou pozici, bude počítána od konce prvního
řetězce.
print_r(substr_compare("Libovolný text", "libovolný porovnávaný text", 10, 0));
Nová délka prvního řetězce je podle čtvrtého parametru nastavena na
"0 znaků"
, na výstup dostaneme hodnotu 0
(shodné
řetězce), protože porovnáváme "nic s ničím".
print_r(substr_compare("Záporná pozice", "pozice", -6, 6));
Hodnota -6
nám udává záporný posun začátku prvního
řetězce. Budou tedy porovnávány řetězce "pozice"
a
"pozice"
. Jelikož jsou tyto řetězce totožné, dostaneme na
výstup hodnotu 0
.
To by pro dnešek ohledně funkcí pro porovnávání řetězců stačilo
V další lekci, Vyhledávání textových řetězců v PHP, si ukážeme funkce pro vyhledávání textových řetězců.