Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sortowanie tablicy a polskie znaki
Forum PHP.pl > Forum > PHP
Myrek
Witam.
Mam problem z polskimi znakami podczas sortowania tablicy. Używam takiego kodu do sortowania:
Kod
function sortowanie($x, $y)

{

if ($x[1] == $y[1])

   return 0;

else if ($x[1] < $y[1])

   return -1;

else

   return 1;

}

usort($tablica, sortowanie);

Skrypt sortuje "zwykłe" wyrazy w tablicy, a te zaczynające się na np. "ś", przerzuca na sam koniec tablicy. Wcale mu się nie dziwię, bo php nie wie gdzie w alfabecie znajduje się litera "ś". Czy jest jakiś sposób na poprawienie tego?
Dzięki za odpowiedzi
Pozdrawiam.
bamboos
Witam!!!
mozesz sprobować najpierw zastąpić pierwsze literki tablicy (jesli sa polskie) np: ś -> sxzz, ć -> cxzz
przesortować i potem spowrotem, ale to trochę naciągane i czaslochłonne. innych pomysłów nie mam smile.gif
Myrek
Nie zadobry pomysł, choć trafny laugh.gif Myślę, że są inne rozwiązania tego problemu, może ktoś je zna?
itsme
posiedziałem trochę i oto jest mój pomysł na rozwiązanie Waszego problemu.
Mamy dwie tablice gdzie w jednej są wyrazy z polskimi literami zaś w drugiej bez polskich liter. Sortujemy druga tablicę (tą bez polskich) za pomoca funkcji asort() czyli należy przyczytać instrukcję.
Następnie jest pętla do wyświetlenia posortowanej drugiej tablicy bez polskich znaków. Zamiast echo "$tablica2[$index]"; wstawiamy tablice z polskimi znakami gdzie zmienna $index określi który wyraz ma się wyświetlić.
Przykład działania znajdziecie TUTAJ
[php:1:6e967699f9]
<?php
$tablica[0]="słoń";
$tablica[1]="masło";
$tablica[2]="cień";
$tablica[3]="leżak";

$tablica2[0]="slon";
$tablica2[1]="maslo";
$tablica2[2]="cien";
$tablica2[3]="lezak";

asort($tablica2);
foreach($tablica2 as $index => $polski)
{
echo "$tablica[$index] $polski<BR>";
}
?>
[/php:1:6e967699f9]
Zapewne ktoś zna lepszy sposób ....
Myrek
Dzięki itsme. Podrasowałem trochę twój skrypt i wyszło mi coś takiego:
Kod
<?

function sortowanie($tablica)

{

$i=0;

foreach ($tablica as $wartosc)

      {     

   $tablica2[$i] = strtr($wartosc, "ąćęłńśżźó", "acelnszxo");

   $i++;

   }

asort($tablica2);

$i=0;

foreach($tablica2 as $index => $xxx)

    {

    $tab[$i] = $tablica[$index];

    $i++;

    }

return $tab;

}



$tablica = sortowanie($tablica);

//wyświetlenie posortowanej tablicy

foreach ($tablica as $wartosc)

      {     

   echo $wartosc;

   echo "<BR>";

   }

?>

Teraz trzeba tylko do funkcji sortowanie przekazać tablice i jest ok. Ale ja mam posortować tablice wielowymiarową. Muszę posiedzieć jeszcze nad tym skryptem i go ulepszyć. Jak to zrobię to umieszczę go tu.
Swoją drogą to dziwne, że nikt nie ma na to gotowego projektu.
itsme
Cytat
$array[0]['name'] = "Niko";
$array[0]['age'] = 24;
$array[1]['name'] = "Dennis";
$array[1]['age'] = 34;

//the fuction:

function array_csort($marray, $column) { //coded by Ichier2003
foreach ($marray as $row) {
$sortarr[] = $row[$column];
}
array_multisort($sortarr, $marray);
return $marray;
}

//just use it like that:

$array = array_csort($array,"age");
zastosowalem rowniez taki kod
[php:1:d8a36897dd]<?php
function csort($array, $column){
$i=0;
for($i=0; $i<count($array); $i++){
$sortarr[]=$array[$i][$column];
}

array_multisort($sortarr, $array);

return($array);
}

?>[/php:1:d8a36897dd]
Oba działąją pięknie
Myrek
itsme, czego wcześniej nie napisałeś, że ten twój kod działa też na polskie znaki, a ja tworzyłem swój biggrin.gif Też działa:
Kod
function sort_wielowymiar($tablica, $kolumna)

{

$i=0;

foreach ($tablica as $wartosc)

      {

   $tablica2[$i] = strtr($wartosc[$kolumna], "ąćęłńśżźó", "acelnszxo");

   $i++;

   }

asort($tablica2);

$i=0;

$ile = count(array_keys($tablica[0]));

foreach($tablica2 as $index => $xxx)

    {

    for ($x=0; $ile>$x; $x++)

  {

     $tab[$i][$x] = $tablica[$index][$x];

  }

    $i++;

    }



return $tab;

}
zombie
Cytat
itsme, czego wcześniej nie napisałeś, że ten twój kod działa też na polskie znaki, a ja tworzyłem swój biggrin.gif Też działa:

Ale to nie załatwia sprawy, bo po sortowaniu wyjdzie
[php:1:63d9380a96]<?php
$posortowane = array("łańcuch", "laska", "łękotka");
?>[/php:1:63d9380a96]
a powinno
[php:1:63d9380a96]<?php
$posortowane = array("laska", "łańcuch", "łękotka");
?>[/php:1:63d9380a96]
czy array_multisort() radzi sobie z tym?
kurtz
Hej

@all: Olaboga.. Po co tak kombinowac ;) locale + strcoll

Zapraszam: http://odothui.jukowski.com/t_79.php


Pozdrawiam
Gonzo
Ja również nie mogę sobie z tym poradzić. Czy ktoś z bardziej wprawionych programistów mógłby poświęcić trochę czasu, aby rozwiązać nasz problem? Z góry bardzo dziękuję.
zombie
Kurtz już sprawę wyjaśnił. :wink:
[php:1:c97ed4ebc2]<?php
setlocale(LC_COLLATE, "pl_PL");
?>[/php:1:c97ed4ebc2]
Gonzo
Chciałbym prosić o gotowy kod, który posortowałby mi taką tablicę:

nazwa_polska||nazwa_oryginalna||liczba_plyt||nazwa_pliku

według pierwszej kolumny. Jestem początkujący, więc mam nadzieję, że ten post nikogo nie rozzłości.
adwol
Cytat
Chciałbym prosić o gotowy kod, który posortowałby mi taką tablicę:

nazwa_polska||nazwa_oryginalna||liczba_plyt||nazwa_pliku

według pierwszej kolumny. Jestem początkujący, więc mam nadzieję, że ten post nikogo nie rozzłości.

Przecież pytałeś już jakiś czas temu o coś bardzo podobnego i dałem Ci wtedy gotowy skrypt bazujący na localach (praktycznie to samo rozwiązanie co podał teraz Kurtz).
Gonzo
Ten skrypt mi nie działa. Próbowałem użyć go na dwóch różnych serwerach, ale bez skutku. Zna ktoś może jakiś inny sposób?
kurtz
Hej
Cytat
Ten skrypt mi nie działa. Próbowałem użyć go na dwóch różnych serwerach, ale bez skutku. Zna ktoś może jakiś inny sposób?
sprawdz co zwraca funkcja setlocale. byc moze na serwerze gdzie testujesz rozwiazanei nie ma wogole polskich lokali albo wysteuje pod inna nazwa - np pl_PL.iso-8859-2 (home.pl bodjaze). Daj znac - jak to nie to bedziemy dalej kombinowali.


Pozdrawiam
Gonzo
Hmmm... Zrobiłem

echo (setlocale(LC_COLLATE, "pl_PL"));

i pokazało się pl_PL.
msulik
Jeśli setlocale nic nie da, to spróbuj tego: [ link ] (pewnie zaraz zostanę obrzucony jajami, ale tym razem akurat to jest o tym tongue.gif )
Gonzo
Eh... Przeczytałeś dokładnie wszystkie posty? Prosiłem o skończony skrypt sortujący tablicę wielowymiarową...
kurtz
Hej
Cytat
Hmmm... Zrobiłem

echo (setlocale(LC_COLLATE, "pl_PL"));

i pokazało się pl_PL.
Skopiuj i wklej skrypt do ktorego adres podalem. Sortuje wg polskich znakow czy nie?


Pozdrawiam
Gonzo
Nie.
msulik
Kurtz, mi to nie działa - sortuje tak, jakby polskie znaki znajdowały się za literą "z". Mam php 4.3.1 pod win więc powinno działać :-|

Gonzo, przepraszam bardzo, to się więcej nie powtórzy...

Cytat
Chciałbym prosić o gotowy kod, który posortowałby mi taką tablicę:

nazwa_polska||nazwa_oryginalna||liczba_plyt||nazwa_pliku

według pierwszej kolumny. Jestem początkujący, więc mam nadzieję, że ten post nikogo nie rozzłości.

Jeśli omawiany wyżej sposób (ten z `setlocale') polskiego sortowania jednowymiarowej tablicy działa Ci normalnie, to spróbuj tak:
Kod
<?php



// Wczytujemy plik do tablicy.

/*

Każda linia pliku jest postaci:

nazwa_polska||nazwa_oryginalna||liczba_plyt||nazwa_pliku

*/

$linie = file ('plik.txt');

$n = count ($linie);



// Zamieniamy elementy tablicy `$linie' na tablice.

for ($i = 0; $i < $n; $i++)

    $linie[$i] = split ('||', rtrim($linie[$i]));



// Teraz każdy element tablicy `$linie' jest tablicą czteroelementową.



// Definiujemy funkcję porównującą.

function mycmp ($a, $b)

{

    // Funkcja `strcoll' to ta, która pojawiła się w omawianym

    // sposobie polskiego sortowania (patrz manual).



    // Porównujemy tylko pierwszą kolumnę.

    return (strcoll($a[0], $b[0]));



    // Funkcja `strcoll' jest `case sensitive', czyli rozróżnia znaki,

    // więc jeśli nie chcemy `case insensitive', trzeba napisać tak:

    /*

    return (strcoll(strtolower($a[0]), strtolower($b[0])));

    */

}



// I teraz to co było wcześniej.

setlocale(LC_COLLATE, 'pl_PL');



// Stosujemy do sortowania naszą funkcję porównującą.

usort($linie, 'mycmp');



reset($linie);

// Wyświetlamy wynik.

foreach ($linie as $linia)

    echo ($linia[0].','.$linia[1].','.$linia[2].','.$linia[3].'<br>');



?>


Powtarzam, u mnie nie działa polskie sortowanie zwykłej tablicy, ale ten sposób powinien działać, jeśli nie ma problemów z setlocale.


Jeśli chodzi o moje rozwiązanie, które podałem w linku, można to zmodyfikować tak (to działa bez `setlocale'):
Kod
<html><head><meta http-equiv="Content-type" content="text/html; charset=windows-1250" /></head><body>

<?php



$convArrayFromPL = array('ą'=>'a/', 'ć'=>'c/', 'ę'=>'e/', 'ł'=>'l/', 'ń'=>'n/', 'ó'=>'o/', 'ś'=>'s/', 'ź'=>'z!', 'ż'=>'z/', 'Ą'=>'A/', 'Ć'=>'C/', 'Ę'=>'E/', 'Ł'=>'L/', 'Ń'=>'N/', 'Ó'=>'O/', 'Ś'=>'S/', 'Ź'=>'Z!', 'Ż'=>'Z/');



$convArrayToPL = array ();

foreach ($convArrayFromPL as $k => $v) $convArrayToPL[$v] = $k;



function codeFromPL ($arg)

{

    global $convArrayFromPL;

    $arg = preg_replace ('/([acelnoszACELNOSZ])/','1 ', $arg);

    return (strtr($arg, $convArrayFromPL));

}



function codeToPL ($arg)

{

    global $convArrayToPL;

    $arg = preg_replace ('/([acelnoszACELNOSZ])s/','1',$arg);

    return (strtr($arg, $convArrayToPL));

}



// Wczytujemy plik do tablicy.

$linie = file ('plik.txt');



// Zamieniamy elementy tablicy `$linie' na tablice.

$n = count ($linie);

for ($i = 0; $i < $n; $i++)

{

    $linie[$i] = split ('||', rtrim($linie[$i]));

    // Kodujemy pierwszą kolumnę.

    $linie[$i][0] = codeFromPL($linie[$i][0]);

}



// Definiujemy funkcję porównującą.

function mycmp ($a, $b)

{

    // Porównujemy tylko pierwszą kolumnę.



    // Funkcja `strcmp' jest `case sensitive', czyli rozróżnia znaki,

    // więc jeśli nie chcemy `case insensitive', trzeba napisać tak:

    return (strcmp(strtolower($a[0]), strtolower($b[0])));

}



// Stosujemy do sortowania naszą funkcję porównującą.

usort($linie, 'mycmp');



// Dekodujemy.

for ($i = 0; $i < $n; $i++)

    $linie[$i][0] = codeToPL($linie[$i][0]);



reset($linie);



// Wyświetlamy wynik.

foreach ($linie as $linia)

    echo ($linia[0].','.$linia[1].','.$linia[2].','.$linia[3].'<br>');



?>
adwol
Cytat
Kurtz, mi to nie działa - sortuje tak, jakby polskie znaki znajdowały się za literą "z". Mam php 4.3.1 pod win więc powinno działać :-|

Pisałem kiedyś, że pod windowsem może to nie działać bo locale to jest patent generalnie uniksowy. Stąd też było kiedyś moje pytanie, czy php pod windows rzeczywiście emuluje locale czy te funkcje (setlocale() i pochodne) są tylko zaślepkami, które nic nie robią.
Gonzo
Wieczorem posprawdzam, czy to działa. A jeśli chodzi o sortowanie z setlocale, to mam z tym duży problem. Niektóre litery wyświetla w dobrej kolejności, ale niektóre nie. Najgorsze jest to, że zamiast zwyczajnie przerzucać na sam koniec tablicy, to umieszcza je [elementy] gdzieś na środku.
orson
witam ...

Cytat
Pisałem kiedyś, że pod windowsem może to nie działać bo locale to jest patent generalnie uniksowy. Stąd też było kiedyś moje pytanie, czy php pod windows rzeczywiście emuluje locale czy te funkcje (setlocale() i pochodne) są tylko zaślepkami, które nic nie robią.


dziala ... mam ustawione:
[php:1:fdabdeaa47]<?php
setlocale(LC_ALL, "Polish");
?>[/php:1:fdabdeaa47]
na winxp pro eng i apache + mysql rowniez na eng
i potem :
[php:1:fdabdeaa47]<?php
$data = strftime("%d %B [%A] - %Y", mktime() );
?>[/php:1:fdabdeaa47]
i dostaje piekna date z polskimi nazwami dni i miesiecy ... w ten sposob mozna spradzic czy dziala ...

uwaga:
ponizej sa linki ze wszystkimi kombinacjami kodow/oznaczen regionalnych ktore przyjmuje set locale ... trzeba sprawdzic ktore dzialaja bo sa zalezne od systemu operacyjnego ...:
http://msdn.microsoft.com/library/default....age_strings.asp
http://msdn.microsoft.com/library/default....try_strings.asp
http://www.unicode.org/onlinedat/countries.html
powinno dzialac ...

cya
Gonzo
Ech... Da mi ktoś w końcu dobry skrypt? Wszystkie poprzednie nie działają dobrze. Sortuję taką tablicę:

nazwa_polska||nazwa_oryginalna||liczba_plyt(int)||nazwa_pliku

na przykład tym skryptem:

[php:1:0e9e671f6e]<?

function cmp ($a, $cool.gif {return strcmp($a[1], $b[1]);}
usort($tablica, "cmp");

?>[/php:1:0e9e671f6e]

albo tym:

[php:1:0e9e671f6e]<?

function array_csort($marray, $column) { //coded by Ichier2003
foreach ($marray as $row) {
$sortarr[] = $row[$column];
}
array_multisort($sortarr, $marray);
return $marray;
}

$tab = array_csort($tablica,0);

?>[/php:1:0e9e671f6e]

Po wykonaniu przez serwer (digital.gda.pl) wyskakuje mi niby wszystko dobrze posortowane, ale prawie wszystkie elementy są podwójne, tzn.

007: Jutro nie umiera nigdy - 007: Tommorow Never Dies 1 CD
007: Jutro nie umiera nigdy - 007: Tommorow Never Dies 1 CD
007: Licencja na zabijanie - 007: Licence to Kill 2 CD
007: Licencja na zabijanie - 007: Licence to Kill 2 CD
007: Moonraker - 007: Moonraker 1 CD
007: Moonraker - 007: Moonraker 1 CD

Nie wiem, co z tym zrobić... :cry:
Gonzo
Kurde :!:

Już chyba wiem, co było problemem laugh.gif. Bawiłem się bazą i ją trochę zwaliłem (przez przypadek zmieniłem format).

Jeżeli coś jeszcze będzie nie tak, dam znać. A wy w tym czasie pogłówkujcie nad sortowaniem z polskimi znakami :wink:.
Gonzo
Wszystko idzie super, ale mam mały problem. Jeżeli chciałbym zajrzeć do bazy i zmienić co nieco, wszystko się posypie. Potrzebuję edytora, który potrafiłby wstawiać na końcu wiersza znaki rn. Inaczej po mnie.

Ma ktoś takie cudeńko? :wink:
lukaszkkk
Cytat(kurtz @ 4.09.2003, 10:56:51 ) *
HejSkopiuj i wklej skrypt do ktorego adres podalem. Sortuje wg polskich znakow czy nie?
Pozdrawiam


Skrypt do ktorego jest link dziala bardzo fajnie.
webdice
~lukaszkkk masz licencje na odkopywanie? Zamykam.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.