Sortowanie stringów z polskimi znakami

Stanęłam ostatnio przed zadaniem posortowanie tablicy zawierającej nazwy miejscowości. Nazwy pobierane były z bazy i zapisane w utf-8. Ani sortowanie w zapytaniu ani standardowe funkcje sortujące dostępne w php nie robiły tego prawidłowo.

Postanowiłam więc sięgnąć po funkcję usort() i zdefiniować własną, jak sądzę, bardzo sprytną funkcję porównującą, która rozwiązała mój problem. Jak wiadomo taka funkcja przyjmuje dwa parametry tj dwie wartości do porównania i musi zdecydować czy są one w poprawnej kolejności czy nie. Poniżej kod funkcji porównującej i objaśnienie:

function sort_m($a, $b){
	$search = array('ę','ó','ą','ś','Ś','ł','Ł','ż','Ż','ź','Ź','ń','Ń');
	$replace = array('ezz','ozz','azz','szz','Szz','lzz','Lzz','zz_','Zz_',
		'zzz','Zzz','nzz','Nzz');
	$a = str_replace($search, $replace,$a);
	$b = str_replace($search, $replace,$b);
	$arrTmp = array($a,$b);
	sort($arrTmp);
	return ($a == $arrTmp[0])? -1:1;
}

Najpierw zdefiniowałam sobie tablice polskich znaków, które mnie interesują (pominęłam kilka wielkich, gdyż nie ma miast na przykład na literę Ą.
Następnie zdefiniowałam listę zamienników. Ponieważ chcę, żeby znak ‘ą’ ustawiał się za ‘a’ zamieniam go na ‘azz’. W ten sposób mam pewność, że stringi ‘kaz’ i ‘kąc’ ustawią się we właściwej kolejności, bo ten drugi zostanie zamieniony (do celów porównania) na ‘kazzc’. W przypadku znaków ‘ź’ i ‘ż’ zastosowałam nieco inne stringi, żeby zapewnić sobie odpowiednie sortowanie tych znaków względem siebie.
Następnie tak zmienione stringi wrzucam do dwuelementowej tablicy i sortuję. Jeśli kolejność nie została zmieniona funkcja porównująca zwraca wartość ujemną w przeciwnym razie wartość dodatnią. I już.

11 komentarzy do wpisu „Sortowanie stringów z polskimi znakami”

  1. A ustawienie COLLATE w mysql nie załatwiłoby sprawy, np:

    SELECT * FROM `wojewodztwa` WHERE 1 ORDER BY `nazwa` COLLATE utf8_polish_ci

  2. hmm to jak ciosanie kamienia innym kamieniem żeby wyszło koło ;) ..
    COLLATE w mysql spokojnie listuje PL ogonki POD WARUNKIEM, że tablica ustawiona jest na utf8_polish_ci
    Pozdrawiam

    • Mam wrażenie, że nie przeczytałeś wszystkiego uważnie. A to nie dobrze, bo uważne czytanie ze zrozumieniem to cnota wielce pożądana u programistów :)

  3. Witam
    Męczę się z tym samym problemem od momentu przekonwertowania bazy z iso do utf8. Wszystko co zaczyna się na Ł, Ż, Ź czy Ś wrzuca po L i czego bym nie spróbował zawsze źle. Baza jest ustawiona na uft8_polish, metoda porównywania też. Gdybym wrzucał przez phpmyadmin, to problemu by nie było, ale używając własnego CMS mam Ĺťywioły zamiast Żywioły… Czy twoja funkcja to jedyne wyjście? UTF8 miało pomagać…

  4. Nie miałem dostępu do bazy bo dane szły z API.
    Nie mogłem dodać bibliotek ani zmienić locale bo nie mam dostępu do serwera (jestem małpą od pisania kodu).

    To jest jedyne rozwiązanie które mogło w moim wypadku zadziałać.

Leave a Reply

%d bloggers like this: