2013-06-27 12 views
6

Próbowałem tylko nauczyć się używać wyrażeń regularnych, więc przepraszam, jeśli niektórym wydaje się to banalne.Zapytanie PHP Regex

Robię mały skrypt crib. Używa standardowej talii kart do gry i używam CDHS (trefl, karo, kier, pik) w garniturach i A2..9TJQK (as, 2 ... 9, 10, jack, królowa, król) dla rang.

Mam zmienną $hand, która jest ciągłym łańcuchem kart. Na przykład: S2HA3D to 2 pik, asa kier i odpowiednio 3 karo. Uwaga: kolor i ranga mogą być dowolne.

Używam:

preg_match_all("/[2-9ATJQK][CDHS]|[CDHS][2-9ATJQK]/i", $hand, $result); 

znaleźć wszystkie karty, ale to zwraca garnitury i szeregi w kolejności znalezionego.

Moje pytanie brzmi: w jaki sposób mogę sprawić, aby wynik dawał pierwszą pozycję dla każdej karty, niezależnie od podanej kolejności. Mam nadzieję, że jasno to sformułowałem.

Odpowiedz

3

Nie sądzę, można to zrobić tylko preg_match.

Ta funkcja jest przeznaczona do dopasowania ciągów, a nie manipulować im. Można jednak zrobić preg_replace w drugim przejściu:

preg_match_all("/[2-9ATJQK][CDHS]|[CDHS][2-9ATJQK]/i", $hand, $rawResult); 
$normalisedResult = preg_replace('/([CDHS])([2-9ATJQK])/i', "$2$1", $rawResult[0]); 

W przypadku wątpliwości, $1 i $2 są wsteczne do grup wskazanych przez nawiasie w pierwszym argumencie preg_replace().

+0

Myślę, że robi to, co chcę najbardziej zwięźle, okrzyki! –

1

Edycja: Na początku nie dostałem poprawnie pytania. tutaj jest to, co trzeba zrobić, trzeba zrobić 2 regex nazywa coś takiego:

/([CDHS])([A2-9TJQK])/i 

następnie:

/([A2-9TJQK])([CDHS])/i 

starać się zmienną, która może pomieścić 1st wartości grupy i 2nd wartość grupy. następnie, aby uzyskać prawidłową rangę, musisz zmienić je na drugi wzór ...

popraw mnie, jeśli się mylę, ale nie możesz tego zrobić z jednym wyrażeniem regularnym.

+0

Czy to nie jest to, co już próbował ... –

+0

zobacz zaktualizowaną odpowiedź – SolidSnake

+0

Czy jest jakiś sposób użycia preg_replace do uporządkowania tych, które są w niewłaściwy sposób?Spojrzałem na http://stackoverflow.com/questions/8411407/looking-for-a-regex-to-find-and-reorder-a-string i pokazuje, że można coś zmienić. Zastanawiałem się, czy istnieje podobne podejście. –

0

Chciałbym użyć wyrażenia regularnego, aby dopasować wszystkie pary, a następnie mieć pewną logikę, aby ponownie dodać ocenę jako pierwszą. Oto co mam na myśli (niesprawdzone)

$grades = array(2,3,4,5,6,7,8,9,'A','T','J','Q','K'); 

preg_match_all('/((C|D|H|S)[2-9ATJQK]{1})|([2-9ATJQK]{1}(C|D|H|S))/i', $subject, $result, PREG_PATTERN_ORDER); 
for ($i = 0; $i < count($result[0]); $i++) { 

    if (in_array($result[0][$i][0], $grades)) { 
     echo ($result[0][$i]); 
    } 
    else { 
     echo (strrev($result[0][$i]));  
    } 

} 
3

Sposobem jest użycie nazwanych zrzuty z modyfikatorem J, który pozwala korzystać z takich samych nazwisk.

$pattern = '~(?J)(?<rk>[2-9ATJQK])?(?<su>[CDHS])(?(1)|(?<rk>[2-9ATJQK]))~i'; 

preg_match_all($pattern, $hand, $matches, PREG_SET_ORDER); 

foreach($matches as $match) { 
    $result .= $match['rk'] . $match['su']; 
} 
echo $result; 

Albo bardziej proste z preg_replace:

$result = preg_replace('~([2-9ATJQK])?([SCHD])(?(1)|([2-9ATJQK]))~i', '$2$1$3', $hand);