IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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ů.


 

Předchozí článek
Porovnávání textových řetězců v PHP
Všechny články v sekci
PHP funkce
Přeskočit článek
(nedoporučujeme)
Vyhledávání textových řetězců v PHP
Článek pro vás napsal Pavel Vaněček
Avatar
Uživatelské hodnocení:
4 hlasů
Autor se věnuje psaní článků na Itnetwork.cz
Aktivity