Autor | Zpráva | ||
---|---|---|---|
Jack06 Profil |
Zdravím, chtěl jsem se zeptat, zda jste někdo neřešil již tento problém:
public static function aplhabetSort($list) { if (!is_array($list)) return $list; setlocale(LC_ALL, "cs_CZ.UTF-8"); usort($list,'strcoll'); return $list; } Seřadí bez diakritiky abecedně a potom s diakritikou. Já bych potřeboval aby to šlo i jako: c, č, d, ď a to mi bohužel nejde. Prosím tedy o radu. Děkuji |
||
Tori Profil |
#2 · Zasláno: 14. 4. 2012, 17:49:19
Mně tohle funguje. Jsou určitě vstupní data v utf8? Je na serveru nainstalovaná česká lokalizace (pokud není, setlocale vrátí false)?
|
||
Jack06 Profil |
Mám VertrigoServ a zkouším to na localhostu na windowsech.
// heh to jsem nezkoušel, vrátí mi false, jak ji nainstalovat? |
||
Davex Profil |
#4 · Zasláno: 14. 4. 2012, 18:15:18
Jack06:
„zkouším to na localhostu na windowsech“ Pro Windows musíš přidat ještě "Czech", ale funguje to trochu divně a nebude to seřazené přesně podle ČSN. Vhodnější nastavení pro UTF-8 se mi najít nepodařilo. setlocale(LC_ALL, "cs_CZ.UTF-8", "Czech"); |
||
Jack06 Profil |
#5 · Zasláno: 14. 4. 2012, 18:21:26
Ani tak se mi to neseřadí podle diakritiky. Jak dostat tu českou lokalizaci do serveru? Nebo kde najdu návod jak ji nainstalovat?
|
||
Davex Profil |
#6 · Zasláno: 14. 4. 2012, 19:06:37
Jack06:
„Jak dostat tu českou lokalizaci do serveru?“ Na Windows asi nijak, protože nefunkčnost řazení v UTF-8 je vlastnost PHP pro Win. Řešením by mohlo být řazení textu v kódování windows-1250 nebo změnit operační systém na Linux, kde to funguje. |
||
Jack06 Profil |
#7 · Zasláno: 14. 4. 2012, 19:31:55
Davex:
No ono to nakonec asi poběží na linuxu, tak by to mohlo být v pohodě. |
||
Tori Profil |
#8 · Zasláno: 14. 4. 2012, 19:50:41
Jack06:
Ještě by pro windows šla dopsat funkce pro definovatelné řazení znaků (obdoba porovnávání v MySQL), ale když to poběží pod linuxem, tak je to asi jedno. |
||
Jack06 Profil |
#9 · Zasláno: 14. 4. 2012, 19:54:04
Tori:
heh asi nevím co tím myslíš. Já doufám, že to dají pod linux :-D |
||
Tori Profil |
Jack06:
Radši nedávám kód, protože to bylo tak narychlo splácané dohromady. Nicméně to fungovalo zhruba takto: // nadefinuju si porovnávání znaků. Znaky z každé skupiny jsou rovnocenné. $collationSetup = array('aAáÁ', 'äÄ', 'bB', 'cCçÇ', 'čČ', )'; // atd. // převedu toto pole do tvaru, kde klíče budou hodnotami, a jednotlivé znaky se změní na klíče: $collation = array('a'=>0, 'A'=>0, 'á'=>0, 'Á'=>0, 'ä'=>1, 'Ä'=>1, 'b'=>2,); // atd. // porovnávací funkce pro usort() function myCmp($string1, $string2) { // z každého řetězce načtu jeden znak pomocí mb_substr() -> $char1, $char2 // porovnávám hodnoty $collation[$char1] a $collation[$char2] // 1. pokud se liší, vrátím 1 nebo -1 // 2. pokud jsem na konci některého ze vstupních řetězců, vrátím 1 nebo -1 (podle kratšího z nich) // 3. pokud se hodnoty shodují, načtu ze vstupů následující znaky a znovu porovnávám } |
||
Jack06 Profil |
#11 · Zasláno: 14. 4. 2012, 20:24:58
Tori:
jojojo au au, tomu jsem se chtěl vyhnout. TZV vlastnímu parseru na sort :-D. Ale moc díky |
||
Aleš Janda Profil |
#12 · Zasláno: 14. 4. 2012, 22:44:58
Tori:
Tohle může většinou stačit, ale zrovna pro české třífázové řazení by to muselo být o něco složitější ;-) |
||
weroro Profil |
#13 · Zasláno: 14. 4. 2012, 23:13:25
Tori:
Je možné do funkcie usort() vložiť compare funkciu (usort(compare))? |
||
Tori Profil |
#14 · Zasláno: 14. 4. 2012, 23:46:24
weroro:
Druhý parametr usort je callback. Takže ano. Aleš Janda: Jasně, neřešila jsem tam ani "ch". Dík za odkaz, zajímavý. |
||
weroro Profil |
#15 · Zasláno: 14. 4. 2012, 23:49:21
Tori:
„Druhý parametr usort je callback. Takže ano.“ Ja PHP neovládam na nejakej vysokej úrovni ale ak sa to dá použiť, tak som v AS napísal a prepísal do PHP niečo takéto. $czStrings = "A,Á,B,C,Č,D,Ď,E,É,Ě,F,G,H,CH,I,Í,J,K,L,M,N,Ň,O,Ó,P,Q,R,Ř,S,Š,T,Ť,U,Ú,Ů,V,W,X,Y,Ý,Z,Ž,a,á,b,c,č,d,ď,e,é,ě,f,g,h,ch,i,í,j,k,l,m,n,ň,o,ó,p,q,r,s,t,ť,u,ú,ů,v,w,x,y,ý,z,ž"; $czStringArray = explode(",", $czStrings); function compare($strA, $strB) { $ret = 0; for ($i = 0; $i < strlen($strA); $i++) { if (getID($strA[$i]) > getID($strB[$i])) { $ret = 1; break; } else if (getID($strA[$i]) < getID($strB[$i])) { $ret = -1; break; } } return $ret; } function getID($char) { $num = count($czStringArray); for ($i = 0; $i < count($czStringArray); $i++) { if ($char == $czStringArray[$i]) { $num = $i; break; } } return $num; } |
||
Jack06 Profil |
#16 · Zasláno: 15. 4. 2012, 10:57:01
velice zajímavé, jen:
1) nebude to moc pomalé?? 2) jak do toho comparu chceš vrazit ty 2 chary? usort($list, array($this, 'compare')); ??? toto nebude stačit Díky za resp |
||
Tori Profil |
#17 · Zasláno: 15. 4. 2012, 11:18:14
weroro:
Řádek 9 bude fungovat jen pro jednobytová kódování, pro utf-8 by muselo být mb_string. Do funkce getID by se v PHP ještě muselo přidat global $czStringArray .
Jack06: Ještě mi napadlo (ale nezkoušela jsem, možná to je blbost): Zkoušel jste nejdřív texty v poli převést na win-1250 a až pak seřadit? |
||
Jack06 Profil |
#18 · Zasláno: 15. 4. 2012, 12:48:39
Tori:
ne nezkoušel :-) a ani mě to nějak nenapadlo :-D |
||
Aleš Janda Profil |
#19 · Zasláno: 15. 4. 2012, 12:51:53
Tori:
„Zkoušel jste nejdřív texty v poli převést na win-1250 a až pak seřadit?“ Ten převod utf-8 => windows-1250 je ale samozřejmě ztrátový, takže nevím, jestli je to jen kvůli seřazení nejlepší nápad. |
||
Jack06 Profil |
#20 · Zasláno: 15. 4. 2012, 13:31:28
Aleš Janda:
iconv je ztrátový? |
||
Aleš Janda Profil |
#21 · Zasláno: 15. 4. 2012, 13:35:48
Jack06:
„iconv je ztrátový?“ Ano. Nelze do kódování windows-1250, jež pojme max. 256 znaků, narvat celou Unicode tabulku s více než 100.000 znaky, které lze zapsat v utf-8. Windows-1250 pokryje jen znaky střední Evropy, zbytek se prostě zahodí. Viz volby //TRANSLIT a //IGNORE pro řízení toho, co se s takovými znaky má stát. |
||
Časová prodleva: 4 roky
|
|||
Čejen Profil * |
#22 · Zasláno: 25. 7. 2016, 11:58:50
Ahoj,
tohle mi funguje i na Windows: usort($array, [new Collator('cs'), 'compare']) |
||
Časová prodleva: 7 měsíců
|
|||
stw Profil * |
#23 · Zasláno: 16. 2. 2017, 19:31:46
Já marně hledal spolehlivě fungující řazení české abecedy, ale když už to umělo diakritiku tak to chybovalo v "Ch".
setlocale(LC_ALL, "cs_CZ.UTF-8", "Czech"); usort($sortarray,'strcoll'); // a nebo sort($sortarray,SORT_LOCALE_STRING); Nakonec sem to vyřešil takto, a funguje znamenitě. usort($sort_user, "SortCzechChars"); function SortCzechChars($a, $b){ $a = str_replace('Ch', 'HZZ', $a); $a = str_replace('ch', 'hzz', $a); $b = str_replace('Ch', 'HZZ', $b); $b = str_replace('ch', 'hzz', $b); static $czechChars = array('A'=>'A','Á'=>'AZ','B'=>'B','C'=>'C','Č'=>'CZ','D'=>'D','Ď'=>'DZ','E'=>'E','É'=>'EZ','Ě'=>'EZZ','F'=>'F','G'=>'G','H'=>'H','I'=>'I','Í'=>'IZ','J'=>'J','K'=>'K','L'=>'L','M'=>'M','N'=>'N','Ň'=>'NZ','O'=>'O','Ó'=>'OZ','P'=>'P','Q'=>'Q','R'=>'R','Ř'=>'RZ','S'=>'S','Š'=>'SZ','T'=>'T','Ť'=>'TZ','U'=>'U','Ú'=>'UZ','Ů'=>'UZZ','V'=>'V','W'=>'W','X'=>'X','Y'=>'Y','Ý'=>'YZ','Z'=>'Z','Ž'=>'ZZ', 'a'=>'a','á'=>'az','b'=>'b','c'=>'c','č'=>'cz','d'=>'d','ď'=>'dz','e'=>'e','é'=>'ez','ě'=>'ezz','f'=>'f','g'=>'g','h'=>'h','i'=>'i','í'=>'iz','j'=>'j','k'=>'k','l'=>'l','m'=>'m','n'=>'n','ň'=>'nz','o'=>'o','ó'=>'oz','p'=>'p','q'=>'q','r'=>'r','ř'=>'rz','s'=>'s','š'=>'sz','t'=>'t','ť'=>'tz','u'=>'u','ú'=>'uz','ů'=>'uzz','v'=>'v','w'=>'w','x'=>'x','y'=>'y','ý'=>'yz','z'=>'z','ž'=>'zz'); $A = strtr($a, $czechChars); $B = strtr($b, $czechChars); return strnatcasecmp($A, $B); } |
||
Keeehi Profil |
#24 · Zasláno: 16. 2. 2017, 19:53:24
stw:
Vyhaž z toho pole identity a bude to ještě lepší. |
||
stw Profil * |
#25 · Zasláno: 18. 2. 2017, 08:20:38
Keeehi:
Ani jsem nečekal že někdo zareaguje ve starém tématu (kde jsem i já hledal řešení). Původně jsem na to šel jinou cestou kde byla potřeba celá abeceda a to byl pozůstatek. Ještě jsem to překopal: usort($sortarray, "SortCzechChars"); function SortCzechChars($a, $b){ static $czechCharsS = array('Á', 'Č', 'Ď', 'É', 'Ě' , 'Ch' , 'Í', 'Ň', 'Ó', 'Ř', 'Š', 'Ť', 'Ú', 'Ů' , 'Ý', 'Ž', 'á', 'č', 'ď', 'é', 'ě' , 'ch' , 'í', 'ň', 'ó', 'ř', 'š', 'ť', 'ú', 'ů' , 'ý', 'ž'); static $czechCharsR = array('AZ','CZ','DZ','EZ','EZZ','HZZZ','IZ','NZ','OZ','RZ','SZ','TZ','UZ','UZZ','YZ','ZZ','az','cz','dz','ez','ezz','hzzz','iz','nz','oz','rz','sz','tz','uz','uzz','yz','zz'); $A = str_replace($czechCharsS, $czechCharsR, $a); $B = str_replace($czechCharsS, $czechCharsR, $b); return strnatcasecmp($A, $B); } Vše řadí perfektně včetně Hž. Ale pokud se vyskytne Hžž (takové slovo neznám :-D) tak ho šoupne až za Ch. |
||
Keeehi Profil |
#26 · Zasláno: 20. 2. 2017, 01:52:29
Pořádně to otestuj, ale toto by mělo korektně řadit jakýkoli český řetězec.
function SortCzechChars($a, $b) { static $order = array('A' => 1, 'Á' => 2, 'B' => 3, 'C' => 4, 'Č' => 5, 'D' => 6, 'Ď' => 7, 'E' => 8, 'É' => 9, 'Ě' => 10, 'F' => 11, 'G' => 12, 'H' => 13, 'Ch' => 14, 'I' => 15, 'Í' => 16, 'J' => 17, 'K' => 18, 'L' => 19, 'M' => 20, 'N' => 21, 'Ň' => 22, 'O' => 23, 'Ó' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'Ř' => 28, 'S' => 29, 'Š' => 30, 'T' => 31, 'Ť' => 32, 'U' => 33, 'Ú' => 34, 'Ů' => 35, 'V' => 36, 'W' => 37, 'X' => 38, 'Y' => 39, 'Ý' => 40, 'Z' => 41, 'Ž' => 42, 'a' => 1, 'á' => 2, 'b' => 3, 'c' => 4, 'č' => 5, 'd' => 6, 'ď' => 7, 'e' => 8, 'é' => 9, 'ě' => 10, 'f' => 11, 'g' => 12, 'h' => 13, 'ch' => 14, 'i' => 15, 'í' => 16, 'j' => 17, 'k' => 18, 'l' => 19, 'm' => 20, 'n' => 21, 'ň' => 22, 'o' => 23, 'ó' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 'ř' => 28, 's' => 29, 'š' => 30, 't' => 31, 'ť' => 32, 'u' => 33, 'ú' => 34, 'ů' => 35, 'v' => 36, 'w' => 37, 'x' => 38, 'y' => 39, 'ý' => 40, 'z' => 41, 'ž' => 42); $a = preg_split('//u', $a, -1, PREG_SPLIT_NO_EMPTY); $b = preg_split('//u', $b, -1, PREG_SPLIT_NO_EMPTY); for($i=0; $i<count($a) && $i<count($b); $i++){ $aChar = $a[$i]; $bChar = $b[$i]; if (($aChar === 'c' || $aChar === 'C') && isset($a[$i+1]) && ($a[$i+1] === 'h' || $a[$i+1] === 'H')) { $aChar .= 'h'; } if (($bChar === 'c' || $bChar === 'C') && isset($b[$i+1]) && ($b[$i+1] === 'h' || $b[$i+1] === 'H')) { $bChar .= 'h'; $i++; } if ($aChar === $bChar) { continue; } $aVal = isset($order[$aChar]) ? $order[$aChar] : 43; $bVal = isset($order[$bChar]) ? $order[$bChar] : 43; if($aVal === $bVal){ continue; } return $aVal - $bVal; } return count($a) - count($b); } |
||
stw Profil * |
#27 · Zasláno: 20. 2. 2017, 18:30:17
Keeehi:
Díky za kód. Určitě si ho uložím, to se může v budoucnu hodit, ale pravděpodobně zůstanu u mého řešení. V rychlém testu mi to řadilo Červ A Čer A Očekával bych je v opačném pořadí. V poli mám skutečná "příjmení jméno;číslo;číslo;číslo;číslo;string" $sortarray[$i] = $user[$i].";".$h[$i].";".$w_h[$i].";".$m[$i].";".$p[$i].";".$string[$i]; V dalších testech jsem si všim zajímavého chování. (I když u mně v praxi ta situace nemůže nikdy nastat.) V poli mám (mimo dalších) Čer A;1;;;;text Čer A;2;;;;text Při každém řazení tyhle dvě prohazuje mezi sebou. |
||
Keeehi Profil |
#28 · Zasláno: 20. 2. 2017, 18:52:57
stw:
Navrhoval jsem to pro řazení slov a ne vět, ovšem změna je velmi jednoduchá, na řádcích 21 a 22 stačí vyměnit číslo 43 za 0 a bude to řadit správně. „Při každém řazení tyhle dvě prohazuje mezi sebou.“ To je dané tím, že řetězce jsou považovány za shodné. Jednička a dvojka nejsou definované v poli $order a všem nedefinovaným znakům je přiřazena hodnota 43 (po úpravě za začátku příspěvku to bude 0). Všechny znaky, podle kterých se má řadit musejí být definované v poli $order . Pokud chceš řadit i podle čísel, stačí je tam přidat.
|
||
Časová prodleva: 7 let
|
0