Autor Zpráva
nugor457
Profil *
Ahojte,

potrebujem vykonat jeden zlozitejsi regularny vyraz, uvediem hned priklad:
<?php
$vztahy = array ( "Peter je kamarat Jano", "Peter je kamarat Vlado","spoluziaci Peter Eva");
$podmienky = array ( "?X je kamarat ?Y", "spoluziaci ?A ?B");

/*
vypis:


1.) 
vztah: 
?X je kamarat ?Y

vysledky:
Peter je kamarat Jano, X = Peter, Y = Jano
Peter je kamarat Vlado, X = Peter, Y = Vlado


2.)
vztah: 
spoluziaci ?A ?B

vysledky:
spoluziaci Peter Eva, A = Peter, B = Eva

*/
?>
Teda, zoberiem prvu podmienku a skusim k tomu najst vsetky vztahy s tym, ze ?A (hocijaky zacinajuci string s otaznikom) je premenna, a to je to co chceme zistit a vypisat. Premenne ?X a ?Y kludne sa mozu rovnat.

Vedeli by ste mi prosim poradit, ako toto cez regularne vyrazy dokazat?

Dakujem velmi pekne.

Moderátor Majkl578: Tvůj projev je špatně srozumitelný, piš prosím s diakritikou.
nemeja
Profil
$regex1 = "~([a-zA-Z]+) je kamarat ([a-zA-Z]+)~";
$vstup1 = "Peter je kamarat Jano";
preg_match($regex1,$vstup1,$vystup1);

array
  0 => string 'Peter je kamarat Jano' (length=21)
  1 => string 'Peter' (length=5)
  2 => string 'Jano' (length=4)
  
  
$regex2 = "~spoluziaci ([a-zA-Z]+) ([a-zA-Z]+)~";
$vstup2 = "spoluziaci Peter Eva";
preg_match($regex2,$vstup2,$vystup2);

array
  0 => string 'spoluziaci Peter Eva' (length=20)
  1 => string 'Peter' (length=5)
  2 => string 'Eva' (length=3)
nugor457
Profil *
nemeja:
Si super, dakujem velmi pekne.

Ale este sa chcem spytat, ako to spravit, tak ze tam budu aj tie otazniky (ako premenne), a to sa potom nejako automaticky nahradi na to ([a-zA-Z]+)
a potom pri vypise bude vediet vypisat aj tie nazvy premennych?

Vopred velka vdaka.
nemeja
Profil
Ne, ale bere se to zleva doprava, takže víš, že ?x == $vystup1[1], atd ;)
Majkl578
Profil
Zkusil jsem si s tím vyhrát víc než nemeja, který to odflákl:
$relations = ['Peter je kamarat Jano', 'Peter je kamarat Vlado', 'spoluziaci Peter Eva'];
$conditions = ['?X je kamarat ?Y', 'spoluziaci ?A ?B'];

// prepare patterns
$patterns = [];
foreach ($conditions as $condition) {
    preg_match_all('~\?[a-z]+~i', $condition, $matches);
    $placeholders = $matches[0];

    $pattern = str_replace(array_map('preg_quote', $placeholders), array_fill(0, count($placeholders), '(\w+)'), preg_quote($condition, '~'));

    $patterns[$pattern] = array_map(function ($item) { return substr($item, 1); }, $placeholders);
}

// do matching
foreach ($relations as $relation) {
    foreach ($patterns as $pattern => $placeholders) {
        if (preg_match('~^' . $pattern . '$~', $relation, $matches)) {
            echo $relation, ': ';

            for ($i = 0, $c = count($placeholders); $i < $c; $i++) {
                echo $placeholders[$i], ' = ', $matches[$i + 1];
                if ($i < $c - 1) echo ', ';
            }

            echo PHP_EOL;

            continue 2;
        }
    }

    echo $relation, ' nemá odpovídající podmínku.', PHP_EOL;
}

Prvně se vezmou podmínky a sestaví se z nich odpovídající reguláry. Následně se projdou všechny věty a zkusí se na ně aplikovat jednotlivé reguláry. V případě shody se vypíší a pokračuje se další větou.
nugor457
Profil *
Si skvely, strasne velmi pekne dakujem.

Otazka:
$conditions = ['?X je kamarat ?Y', 'spoluziaci ?A ?B']; musim nahradit $conditions = array ('?X je kamarat ?Y', 'spoluziaci ?A ?B'); inak pise chybu, tebe to hentak ide?

Este raz dakujem.
Majkl578
Profil
[#6] nugor457:
Je to tak, stačí to nahradit. Od PHP 5.4 (kterou používám) jde pole psát i kratší formou, jakou jsem použil. Tedy [...] je ekvivalentní array(...). Na zbytek stačí PHP 5.3.
nugor457
Profil *
Majkl578:
ok, dakujem moc, verim, ze uz si s mojim problemom poradim (toto bola podmnozina co chcem spavit) :)
(keby nieco, urcite sa este ozvem)

dakujem za vas cas.
nugor457
Profil *
Problem:

tie podmienky mozu byt aj rovnake LEN s inymi nazvami premennych, napriklad:

$conditions = ['?X je kamarat ?Y', '?X je kamarat ?A', 'spoluziaci ?A ?B'];

v tomto pripade, to spravi len jednu z tych prvych dvoch.

Da sa to opravit?
Majkl578
Profil
nugor457:
Dá, jen je třeba vyhodit řádky 28 a 32 a mírně upravit způsob uchování připravených patternů a podmínek:
$relations = ['Peter je kamarat Jano', 'Peter je kamarat Vlado', 'spoluziaci Peter Eva'];
$conditions = ['?X je kamarat ?Y', '?X je kamarat ?A', 'spoluziaci ?A ?B'];
 
// prepare patterns
$preparedConditions = [];
foreach ($conditions as $condition) {
    preg_match_all('~\?[a-z]+~i', $condition, $matches);
    $placeholders = $matches[0];
 
    $pattern = str_replace(array_map('preg_quote', $placeholders), array_fill(0, count($placeholders), '(\w+)'), preg_quote($condition, '~'));
 
    $preparedConditions[$condition] = [$pattern, array_map(function ($item) { return substr($item, 1); }, $placeholders)];
}
 
// do matching
foreach ($relations as $relation) {
    foreach ($preparedConditions as $condition) {
        list ($pattern, $placeholders) = $condition;

        if (preg_match('~^' . $pattern . '$~', $relation, $matches)) {
            echo $relation, ': ';
 
            for ($i = 0, $c = count($placeholders); $i < $c; $i++) {
                echo $placeholders[$i], ' = ', $matches[$i + 1];
                if ($i < $c - 1) echo ', ';
            }
 
            echo PHP_EOL;
        }
    }
}
Generuje:
Peter je kamarat Jano: X = Peter, Y = Jano
Peter je kamarat Jano: X = Peter, A = Jano
Peter je kamarat Vlado: X = Peter, Y = Vlado
Peter je kamarat Vlado: X = Peter, A = Vlado
spoluziaci Peter Eva: A = Peter, B = Eva 

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: