koalvi.blogspot.com - другой мой блог "сойдет на троечку"

суббота, 14 ноября 2015 г.

Сортировка PHP и национальные символы (українська І, Є) в 2x массиве.

******* код, реально работающий в проекте
<?
function sort_uk( $a, $b ){
$a = mb_strtoupper ( $a, 'UTF-8' );
$b = mb_strtoupper ( $b, 'UTF-8' );
$alphabet = array(
'А' => 1, 'Б' => 2, 'В' => 3, 'Г' => 4, 'Д' => 5, 'Е' => 6, 'Є' => 7, 'Ж' => 8, 'З' => 9, 'И' => 10, 'І' => 11,
'Ї' => 12, 'Й' => 13, 'К' => 14, 'Л' => 15, 'М' => 16, 'Н' => 17, 'О' => 18, 'П' => 19, 'Р' => 20, 'С' => 21, 'Т' => 22,
'У' => 23, 'Ф' => 24, 'Х' => 25, 'Ц' => 26, 'Ч' => 27, 'Ш' => 28, 'Щ' => 29, 'Ь' => 30, 'Ю' => 31, 'Я' => 32);
$lengthA = mb_strlen ( $a, 'UTF-8' );
$lengthB = mb_strlen ( $b, 'UTF-8' );
for( $i = 0; $i < ( $lengthA > $lengthB? $lengthB: $lengthA ); $i++ ){
   if ( $alphabet[ mb_substr( $a, $i, 1, 'UTF-8' ) ] < $alphabet[ mb_substr( $b, $i, 1, 'UTF-8' ) ]){           $status = -1;          break;       }
    elseif ( $alphabet[ mb_substr( $a, $i, 1, 'UTF-8' ) ] > $alphabet[ mb_substr( $b, $i, 1, 'UTF-8' ) ] ){ $status = 1; break; }
       else{ $status = 0; } }
   return $status;}
function sort_array2x($data,$st)
{
//echo 'oops';
for($i=0;$i<count($data);$i++) {$a=$data[$i][$st];$data[$i][$st]=$data[$i][0];$data[$i][0]=$a;}
$ii=0;for($i=0;$i<count($data);$i++)
       for($j=0;$j<count($data[0]);$j++)
         if($j<count($data[0])-1) $ndata[$i].=$data[$i][$j].'|';  else $ndata[$i].=$data[$i][$j];
//print_r( $ndata);
usort($ndata, 'sort_uk');
 
//print_r($ndata);
for($i=0;$i<count($ndata);$i++) $data[$i]=explode("|",$ndata[$i]);
//echo "<BR>";print_r($data);
for($i=0;$i<count($ndata);$i++) {$a=$data[$i][$st];$data[$i][$st]=$data[$i][0];$data[$i][0]=$a;}
return $data;}
?>
*******
"Кусок кода" (состоит из класса и функции) для сортировки таблицы с кириллицей и нац.укр.символами, решал проблему с правильной сортировкой украинских фамилий без участия MySql (он как раз нормально делает order by fam).
пример использования:
$data=sort_array2x($data,1) где 1- номер второго столбца.
Для сортировки обычного списка (одномерного) можно использовать
usort($data, 'utf_8_UA::cmp');
========= php ==
class utf_8_UA
{static $order = '0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZzАаБбВвГгДдЕеЄєЖжЗзИиІіЇїЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЬьЮюЯя';
 static $char2order;
 static function cmp($a, $b) {
    if ($a == $b)  return 0;  
    if (empty(self::$char2order))
    { $order = 1;$len = mb_strlen(self::$order);
      for ($order=0; $order<$len; ++$order) self::$char2order[mb_substr(self::$order, $order, 1)] = $order;}
     $len_a = mb_strlen($a);$len_b = mb_strlen($b);$max=min($len_a, $len_b);
    for($i=0; $i<$max; ++$i)
    { $char_a= mb_substr($a, $i, 1);$char_b= mb_substr($b, $i, 1);
      if ($char_a == $char_b) continue;
      $order_a = (isset(self::$char2order[$char_a])) ? self::$char2order[$char_a] : 9999;
      $order_b = (isset(self::$char2order[$char_b])) ? self::$char2order[$char_b] : 9999;
       return ($order_a < $order_b) ? -1 : 1;}return ($len_a < $len_b) ? -1 : 1;  }}
function sort_array2x($data,$st)
{for($i=0;$i<count($data);$i++) {$a=$data[$i][$st];$data[$i][$st]=$data[$i][0];$data[$i][0]=$a;}
$ii=0;for($i=0;$i<count($data);$i++)
       for($j=0;$j<count($data[0]);$j++)
         if($j<count($data[0])-1) $ndata[$i].=$data[$i][$j].'|';  else $ndata[$i].=$data[$i][$j];
usort($ndata, 'utf_8_UA::cmp');
for($i=0;$i<count($ndata);$i++) $data[$i]=explode("|",$ndata[$i]);
for($i=0;$i<count($ndata);$i++) {$a=$data[$i][$st];$data[$i][$st]=$data[$i][0];$data[$i][0]=$a;}
return $data;}
=========== php
PS. Класс заимствовал (спасибо w-dot-rosenbach-at-netskill-de за мотивы), функция моя не претендует на идеал, но для меня логично работает, легкие аналоги на глаза не попадались.
(C) Коваленко Александр


а вот еще вариант Sergic - лучший ответ от  mysqlru.com
=== php
function sort_uk( $a, $b ){
$a = mb_strtoupper ( $a, 'UTF-8' );
$b = mb_strtoupper ( $b, 'UTF-8' );
$alphabet = array(
'А' => 1, 'Б' => 2, 'В' => 3, 'Г' => 4, 'Д' => 5, 'Е' => 6, 'Є' => 7, 'Ж' => 8, 'З' => 9, 'И' => 10, 'І' => 11,
'Ї' => 12, 'Й' => 13, 'К' => 14, 'Л' => 15, 'М' => 16, 'Н' => 17, 'О' => 18, 'П' => 19, 'Р' => 20, 'С' => 21, 'Т' => 22,
'У' => 23, 'Ф' => 24, 'Х' => 25, 'Ц' => 26, 'Ч' => 27, 'Ш' => 28, 'Щ' => 29, 'Ь' => 30, 'Ю' => 31, 'Я' => 32);
$lengthA = mb_strlen ( $a, 'UTF-8' );
$lengthB = mb_strlen ( $b, 'UTF-8' );
for( $i = 0; $i < ( $lengthA > $lengthB? $lengthB: $lengthA ); $i++ ){
   if ( $alphabet[ mb_substr( $a, $i, 1, 'UTF-8' ) ] < $alphabet[ mb_substr( $b, $i, 1, 'UTF-8' ) ]){           $status = -1;          break;       }
    elseif ( $alphabet[ mb_substr( $a, $i, 1, 'UTF-8' ) ] > $alphabet[ mb_substr( $b, $i, 1, 'UTF-8' ) ] ){ $status = 1; break; }
       else{ $status = 0; } }
   return $status;}
 
uasort($arr, 'sort_uk');
=== 
а вот еще хороший ресурс про двумерные массивы
http://www.the-art-of-web.com/php/sortarray/

1 комментарий:

  1. при внедрении функций в рабочий проект вариант с классами отказался работать, поэтому удачной версией считаю что-то среднее между первым кодом и вторым

    ОтветитьУдалить