Автор Тема: Некоректно сортиране в PHP  (Прочетена 4898 пъти)

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Некоректно сортиране в PHP
« -: Apr 14, 2014, 19:12 »
Здравейте,
опитвам се да сортирам 2 свързани масива, като използвам

array_multisort($ar1,SORT_ASC,$ar2);

когато използвам като тестов пример
$ar1=Array
(
   
  • => ябълка
  • [1] => круша
        [2] => кайсия
        [3] => слива
    )
    -----------------------
    -----------------------
    $ar2=Array
    (
       
  • => иван
  • [1] => петър
        [2] => стоян
        [3] => иван
    )
    всичко е наред и резултатът е
    $ar1=Array
    (
       
  • => кайсия
  • [1] => круша
        [2] => слива
        [3] => ябълка
    )
    -----------------------
    -----------------------
    $ar2=Array
    (
       
  • => стоян
  • [1] => петър
        [2] => иван
        [3] => иван
    )
    Когато обаче използвам реални данни (от MySql таблица):
    $ar1=Array
    (
       
  • => Аида
  • [1] => Симфоничен концерт
        [2] => Ноктюрно
        [3] => Пролетно тайнство
        [4] => La Traviata
        [5] => Цвета
    )
    -----------------------
    -----------------------
    $ar2=Array
    (
       
  • => Verdi, Giuseppe
  • [1] => Бетовен, Лудвиг ван
        [2] => Лист, Ференц
        [3] => Стравински Игор
        [4] => Verdi, Giuseppe
        [5] => Атанасов, Маестро Георги
    )

    След подреждането:

    $ar1=Array
    (
       
  • => Аида
  • [1] => Симфоничен концерт
        [2] => Ноктюрно
        [3] => Пролетно тайнство
        [4] => La Traviata
        [5] => Цвета
    )
    -----------------------
    -----------------------
    $ar2=Array
    (
       
  • => Верди, Джузепе
  • [1] => Бетовен, Лудвиг ван
        [2] => Лист, Ференц
        [3] => Стравински, Игор
        [4] => Verdi, Giuseppe
        [5] => Атанасов, Маестро Георги
    )
    -----------------------
    т. е. няма коректно подреждане.
    Използването на
    setlocale(LC_ALL,'bg_BG.UTF-8'); и опциите
    SORT_LOCALE_STRING или SORT_STRING не променя резултата.
    Таблицата ми е с колация utf8_general_ci.
    Къде греша?

    ПС Системата ми преформатира индексите, първият не е точка (bullet), а 0 (нула).
Активен

pennywise

  • Гост
Re: Некоректно сортиране в PHP
« Отговор #1 -: Apr 14, 2014, 19:41 »
Можеш ли да сложиш кода в пейстбин или нещо подобно така както е?
Активен

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #2 -: Apr 14, 2014, 22:42 »
Не просто няма коректно подреждане, ами няма никакво подреждане - поредността им си е останала същата. Нещо явно бъркаш изначално, така че наистина трябва да видим истинския код, който изпълняваш. А и двете (тестовият и реалният примери) ли ги изпълняваш през един и същи интерпретатор, или например едното го изпълняваш в конзолата, а другото - през браузъра?
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #3 -: Apr 16, 2014, 08:48 »
Данните са от таблицата (това са всичките данни от нея). Ако дам сортиране по низходящ ред:
Array
(
   
  • => Цвета
  • [1] => La Traviata
        [2] => Пролетно тайнство
        [3] => Ноктюрно
        [4] => Симфоничен концерт
        [5] => Аида
    )
    т. е. обръща се реда, но взаимното положение на елементите се запазва. Това се получава при реалните данни от базата, a когато въведа ръчно същите данни в масивите всичко е ОК:
    -----------------------
    Array
    (
       
  • => Аида
  • [1] => Ноктюрно
        [2] => Пролетно тайнство
        [3] => Симфоничен концерт
        [4] => Цвета
        [5] => La Traviata
    )
    -----------------------
    -----------------------
    Array
    (
       
  • => Верди, Джузепе
  • [1] => Лист, Ференц
        [2] => Стравински, Игор
        [3] => Бетовен, Лудвиг ван
        [4] => Атанасов, Маестро Георги
        [5] => Verdi, Giuseppe
    )
    -----------------------
    Затова предполагам, че е нещо свързано с колацията. Но какво?
Активен

BRADATA

  • Напреднали
  • *****
  • Публикации: 833
  • Distribution: Slackware/Mint/CentOS
  • Window Manager: console/KDE/LXDE
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #4 -: Apr 16, 2014, 09:10 »
Човече, няма как да се помогне ако не видим ПРОГРАМНИЯ КОД НА СОРТИРАЩАТА ФУНКЦИЯ. Данните са ясни - дай да видим какво си натворил във функцията.
Активен

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #5 -: Apr 16, 2014, 11:52 »
Визуализацията се вика с:
Код:
$title='Произведение';
render($title,$viewDir.'ls_operas',$result);

Функция render:
Код:
function render($title,$name,$data=array(),$data1=array()){ 
require $name.'.php';
}

Входни данни - масив $result:
Код:
Array
(
    [0] => Array
        (
            [opera_title] => Аида
            [composers] => Верди, Джузепе; Verdi, Giuseppe
        )

    [1] => Array
        (
            [opera_title] => Симфоничен концерт
            [composers] => Бетовен, Лудвиг ван; Стравински, Игор
        )

    [2] => Array
        (
            [opera_title] => Ноктюрно
            [composers] => Лист, Ференц
        )

    [3] => Array
        (
            [opera_title] => Пролетно тайнство
            [composers] => Стравински, Игор
        )

    [4] => Array
        (
            [opera_title] => La Traviata
            [composers] => Верди, Джузепе; Verdi, Giuseppe
        )

    [5] => Array
        (
            [opera_title] => Цвета
            [composers] => Атанасов, Маестро Георги
        )

)

Визуализация - ls_operas.php:
Цитат
<?php
   include './inc/header.php';
   echo '<section><article><header>';
   echo '<h1>'.$title.'</h1></header>';
//   dump($data);
   $opera_title=array();
   $composers=array();
   foreach ($data as $value) {
      $opera_title[]=$value['opera_title'];
      $composers[]=$value['composers'];
   }
   setlocale(LC_ALL,'bg_BG.UTF-8');
   if(!isset($order)){
      $order='SORT_ASC';
   }
   if (isset($_GET['o_order'])) {
      /* сортираме имената на произведенията */
      $order=$_GET['order'];
      switch ($_GET['col']) {
         case 1:
            $ar1=$opera_title;
            $ar2=$composers;
            break;
         case 2:
            $ar1=$composers;
            $ar2=$opera_title;
            break;
      }
/* за проба - работи както трябва
$ar1=array('Аида','Симфоничен концерт','Ноктюрно','Пролетно тайнство','La Traviata','Цвета');
$ar2=array('Верди, Джузепе','Бетовен, Лудвиг ван','Лист, Ференц','Стравински, Игор','Verdi, Giuseppe','Атанасов, Маестро Георги');
*/
      switch ($order) {
         case 'SORT_ASC':
            array_multisort($ar1,SORT_ASC,SORT_LOCALE_STRING,$ar2);
            $order='SORT_DESC';
            break;
         case 'SORT_DESC':
            array_multisort($ar1,SORT_DESC,SORT_LOCALE_STRING,$ar2);
            $order='SORT_ASC';
            break;
      }
   }
   if(isset($_GET['col'])){
      switch ($_GET['col']) {
         case 1:
            $opera_title=$ar1;
            $composers=$ar2;
            break;
         case 2:
            $opera_title=$ar2;
            $composers=$ar1;
            break;
      }
   }
   echo '<table>
         <thead><tr>
         <th><a href="index.php?page=operas&o_order=true&order='.$order.'&col=1">Произведение</a></th><th><a href="index.php?page=operas&o_order=true&order='.$order.'&col=2">Композитори</a></th>
         </tr></thead><tbody>';
      for ($i=0;$i<count($opera_title);$i++) {
          echo '<tr><td>';
         echo $opera_title[$i].'</td><td>';
         echo $composers[$i] . '</td></tr>';
      }
      echo '</tbody></table>
   </article></section>';
   include './inc/footer.php';

Смених в базата колацията от utf8_general_ci на utf8_unicode_ci - без промяна.
Активен

BRADATA

  • Напреднали
  • *****
  • Публикации: 833
  • Distribution: Slackware/Mint/CentOS
  • Window Manager: console/KDE/LXDE
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #6 -: Apr 16, 2014, 18:11 »
setlocale(LC_ALL,'bg_BG.UTF-8')

е добре да се постави в началото. Как се появяват данните в $data? Какво е кодирането им тогава?
Активен

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #7 -: Apr 16, 2014, 20:22 »
Данните в $data (всъщност $result като параметър на функцията render) са резултат от обработка на прочетените данни за дублиране на имена (aka, alias) т. е. „Верди“=„Verdi“, „Цвета“=„Македонска кървава сватба“ и т. н., като съвпадащите имена са в един запис. Кодирането им e UTF-8 (проверено с echo mb_detect_encoding($ar1[0],"auto",true);), тъй като още в началото давам mb_internal_encoding('UTF-8');
Поставянето на setlocale не променя нищо, т. е. сортирането продължава да е некоректно.
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Некоректно сортиране в PHP
« Отговор #8 -: Apr 16, 2014, 22:15 »
Така, почваме като малките деца (извинявам се че така те подхванах, но какво да се прави - просто така си си задал въпроса):

0. Пускаш да ти плюе всички грешки от конфигурацията на PHP
1. Каква версия ти е PHP интерпретатора на работната среда (тестовия сървър).
2. Трябва да стане ясно какво точно се опитваш да направиш - това най-ясно се изразява с пример (Просто ни дай примерен резултат).
3. Погледни този примерен код (http://codepad.org/9MCJSVKp) и помисли над него.  Искаш да се получава това, което се получава? - а то е следното:

а. Подрежда първия масив по зададения ключ - SORT_ASC + SORT_STRING.
b. Подрежда втория масив по начин съответстващ на позициите на първия масив.
За по-добро обяснение погледни официалната документацията на функцията и примерите под нея: array_multisort php.net

4. В по-старите версии на PHP, флага SORT_LOCALE_STRING изглежда, че е невалиден!
Затова винаги трябва да си пускаш всички грешки при разработване на код.

Ако това не ти е достатъчно за решаването на проблема - явно нещо друго е оплескано, което пропускам.
« Последна редакция: Apr 16, 2014, 22:19 от !ntel »
Активен

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #9 -: Apr 17, 2014, 11:16 »
@Intel, по точки:
0. error_reporting(E_ALL); няма съобщения за грешки
1. PHP Version 5.3.2-1ubuntu4.24
2. искам да получа
Код:
    [0] => Аида
    [1] => Ноктюрно
    [2] => Пролетно тайнство
    [3] => Симфоничен концерт
    [4] => Цвета
    [5] => La Traviata
)
-----------------------
-----------------------
Array
(
    [0] => Верди, Джузепе
    [1] => Лист, Ференц
    [2] => Стравински, Игор
    [3] => Бетовен, Лудвиг ван
    [4] => Атанасов, Маестро Георги
    [5] => Verdi, Giuseppe
)
3. Когато $ar1 и $ar2 са зададени имплицитно, както е в твоя код, всичко е ОК. Когато масивите са запълнени с данни от базата, въпреки че като разпечатка изглеждат еднакво, сортирането не се получава. Зададени са:
Код:
mb_internal_encoding('UTF-8');
setlocale(LC_ALL,'bg_BG.UTF-8');
$db = mysqli_connect('localhost', 'user', 'pass', 'database');
if (!$db) {
    echo 'No database';
}
error_reporting(E_ALL);
mysqli_set_charset($db, 'utf8');
a. да
b. да
От цитираната документация останах с впечатлението, че SORT_ASC/DESC,SORT_STRING не са необходими за втория масив. Така или иначе, и с добавянето им нищо не се променя - записите остават като моментна „картинка“, като не променят взаимното си положение (когато са от базата).
4. Виж т. 1
Цитат
явно нещо друго е оплескано, което пропускам.
и аз, подозирам колациите - с utf8_general_ci и utf8_unicode_ci резултатът е еднакъв, т. е. никакъв.
Активен

senser

  • Напреднали
  • *****
  • Публикации: 1328
    • Профил
Re: Некоректно сортиране в PHP
« Отговор #10 -: Apr 17, 2014, 11:18 »
Защо не пробваш със записи от базата само с латински букви, т.е. без кирилица.
Активен

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #11 -: Apr 17, 2014, 12:15 »
@senser, пробвах - подреждането е същото. Но това ме наведе на друга мисъл - първосигнално съм задал некоректен въпрос - към всеки запис от базата се добавя линк с id-то, така че сортирането де факто е по линкове и само по себе си е коректно. Когато данните са въведени ръчно в масивите, линковете липсват и там сортирането е друго.
Благодаря на всички  отзовали се и се извинявам за изгубеното време!  [_]3
Активен

kifavi8024

  • Новаци
  • *
  • Публикации: 0
    • Профил
Re: Некоректно сортиране в PHP
« Отговор #12 -: Apr 18, 2014, 02:52 »
И аз се радвам, че си намерил грешката в кода. :)
Във форума няма такова нещо като изгубено време - някой ден, някой друг ще търси за подобен проблем и тази тема най-вероятно ще му помогне  [_]3
Активен

angie_bg

  • Напреднали
  • *****
  • Публикации: 842
  • Distribution: Ubuntu 10.04
  • Window Manager: Gnome
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #13 -: Apr 22, 2014, 20:52 »
Без да претендирам за оптималност или елегантност, моето решение:
Входящи данни:
Код:
-----------------------
Array
(
    [0] => Array
        (
            [opera_title] => Аида
            [composers] => Верди, Джузепе; Verdi, Giuseppe
        )

    [1] => Array
        (
            [opera_title] => Симфоничен концерт
            [composers] => Бетовен, Лудвиг ван; Стравински, Игор
        )

    [2] => Array
        (
            [opera_title] => Ноктюрно
            [composers] => Лист, Ференц
        )

    [3] => Array
        (
            [opera_title] => Le Sacre du printemps
            [composers] => Стравински, Игор
        )

    [4] => Array
        (
            [opera_title] => La Traviata
            [composers] => Верди, Джузепе; Verdi, Giuseppe
        )

    [5] => Array
        (
            [opera_title] => Цвета
            [composers] => Атанасов, Маестро Георги
        )

)
-----------------------
Визуализация:
Код:
<?php
include './inc/header.php';
echo '<section><article><header>';
echo '<h1>'.$title.'</h1></header>';
if(!isset($order)){
$order='ASC';
}
if (isset($_GET['o_order'])) {
/* сортираме имената на произведенията */
$order=$_GET['order'];
if(isset($_GET['col'])){
switch ($_GET['col']) {
case 1:
$data=sort_ot($data,$order);
break;
case 2:
$data=sort_c($data,$order);
break;
}
switch ($order) {
case 'ASC':
$order='DESC';
break;
case 'DESC':
$order='ASC';
break;
}
}
}
echo '<table>
<thead><tr>
<th><a href="index.php?page=operas&o_order=true&order='.$order.'&col=1">Произведение</a></th><th><a href="index.php?page=operas&o_order=true&order='.$order.'&col=2">Композитори</a></th>
</tr></thead><tbody>';
for ($i=0;$i<count($data);$i++) {
    echo '<tr><td>';
//     echo preg_match(">.+<",$opera_title[$i]);
echo $data[$i]['opera_title'].'</td><td>';
echo $data[$i]['composers']. '</td></tr>';
}
echo '</tbody></table>
</article></section>';
include './inc/footer.php';
Сортиране:
Код:
function sort_ot ($data,$order) {
    switch ($order) {
        case 'ASC':
            usort($data,'cmp_ot');
            break;
        case 'DESC':
            usort($data,'cmp_otr');
            break;
    }
    return $data;
}

function cmp_ot($a,$b) {
    $x=substr($a['opera_title'],strpos($a['opera_title'],'>')+1, strrpos($a['opera_title'],'<',strpos($a['opera_title'],'>'))-strpos($a['opera_title'],'>')-1);
    $y=substr($b['opera_title'],strpos($b['opera_title'],'>')+1, strrpos($b['opera_title'],'<',strpos($b['opera_title'],'>'))-strpos($b['opera_title'],'>')-1);
    if ($x === $y) {
        return 0;
    } elseif ($x < $y) {
        return -1;
    } else {
        return 1;
    }
}

function cmp_otr($a,$b) {
    $x=substr($a['opera_title'],strpos($a['opera_title'],'>')+1, strrpos($a['opera_title'],'<',strpos($a['opera_title'],'>'))-strpos($a['opera_title'],'>')-1);
    $y=substr($b['opera_title'],strpos($b['opera_title'],'>')+1, strrpos($b['opera_title'],'<',strpos($b['opera_title'],'>'))-strpos($b['opera_title'],'>')-1);
    if ($x === $y) {
        return 0;
    } elseif ($x > $y) {
        return -1;
    } else {
        return 1;
    }

}

function sort_c ($data,$order) {
    switch ($order) {
        case 'ASC':
            usort($data,'cmp_c');
            break;
        case 'DESC':
            usort($data,'cmp_cr');
            break;
    }
    return $data;
}

function cmp_c($a,$b) {
    $x=substr($a['composers'],strpos($a['composers'],'>')+1, strrpos($a['composers'],'<',strpos($a['composers'],'>'))-strpos($a['composers'],'>')-1);
    $y=substr($b['composers'],strpos($b['composers'],'>')+1, strrpos($b['composers'],'<',strpos($b['composers'],'>'))-strpos($b['composers'],'>')-1);
    if ($x === $y) {
        return 0;
    } elseif ($x < $y) {
        return -1;
    } else {
        return 1;
    }
}

function cmp_cr($a,$b) {
    $x=substr($a['composers'],strpos($a['composers'],'>')+1, strrpos($a['composers'],'<',strpos($a['composers'],'>'))-strpos($a['composers'],'>')-1);
    $y=substr($b['composers'],strpos($b['composers'],'>')+1, strrpos($b['composers'],'<',strpos($b['composers'],'>'))-strpos($b['composers'],'>')-1);
    if ($x === $y) {
        return 0;
    } elseif ($x > $y) {
        return -1;
    } else {
        return 1;
    }

}

Допълнителен въпрос: какъв dump, print_r или нещо друго мога да ползвам, така че вместо „Цвета“ да ми излиза реалното „<a href="index.php?page=spectacles&amp;opera_id=6">Цвета</a>“?
Активен

go_fire

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 8780
  • Distribution: Дебиан Сид
  • Window Manager: ROX-Desktop / е17
  • кашик с гранатомет в танково поделение
    • Профил
    • WWW
Re: Некоректно сортиране в PHP
« Отговор #14 -: Apr 22, 2014, 21:06 »
Ехо?
Активен

В $por4e2 e истината  ;)

***

Aко даваха стипендия за най-глупави, щях да съм човека с най-много Mини Kупъри

***

Reborn since 1998 || 15.09.2007 totally М$ free && conscience clear