Linux за българи: Форуми

Програмиране => Web development => Темата е започната от: angie_bg в Apr 14, 2014, 19:12



Титла: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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 (нула).


Титла: Re: Некоректно сортиране в PHP
Публикувано от: pennywise в Apr 14, 2014, 19:41
Можеш ли да сложиш кода в пейстбин или нещо подобно така както е?


Титла: Re: Некоректно сортиране в PHP
Публикувано от: neter в Apr 14, 2014, 22:42
Не просто няма коректно подреждане, ами няма никакво подреждане - поредността им си е останала същата. Нещо явно бъркаш изначално, така че наистина трябва да видим истинския код, който изпълняваш. А и двете (тестовият и реалният примери) ли ги изпълняваш през един и същи интерпретатор, или например едното го изпълняваш в конзолата, а другото - през браузъра?


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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
    )
    -----------------------
    Затова предполагам, че е нещо свързано с колацията. Но какво?


Титла: Re: Некоректно сортиране в PHP
Публикувано от: BRADATA в Apr 16, 2014, 09:10
Човече, няма как да се помогне ако не видим ПРОГРАМНИЯ КОД НА СОРТИРАЩАТА ФУНКЦИЯ. Данните са ясни - дай да видим какво си натворил във функцията.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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 - без промяна.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: BRADATA в Apr 16, 2014, 18:11
setlocale(LC_ALL,'bg_BG.UTF-8')

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


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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 не променя нищо, т. е. сортирането продължава да е некоректно.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: kifavi8024 в Apr 16, 2014, 22:15
Така, почваме като малките деца (извинявам се че така те подхванах, но какво да се прави - просто така си си задал въпроса):

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

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

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

Ако това не ти е достатъчно за решаването на проблема - явно нещо друго е оплескано, което пропускам.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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 резултатът е еднакъв, т. е. никакъв.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: senser в Apr 17, 2014, 11:18
Защо не пробваш със записи от базата само с латински букви, т.е. без кирилица.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в Apr 17, 2014, 12:15
@senser, пробвах - подреждането е същото. Но това ме наведе на друга мисъл - първосигнално съм задал некоректен въпрос - към всеки запис от базата се добавя линк с id-то, така че сортирането де факто е по линкове и само по себе си е коректно. Когато данните са въведени ръчно в масивите, линковете липсват и там сортирането е друго.
Благодаря на всички  отзовали се и се извинявам за изгубеното време!  [_]3


Титла: Re: Некоректно сортиране в PHP
Публикувано от: kifavi8024 в Apr 18, 2014, 02:52
И аз се радвам, че си намерил грешката в кода. :)
Във форума няма такова нещо като изгубено време - някой ден, някой друг ще търси за подобен проблем и тази тема най-вероятно ще му помогне  [_]3


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в 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>“?


Титла: Re: Некоректно сортиране в PHP
Публикувано от: go_fire в Apr 22, 2014, 21:06
Ехо?


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в Apr 23, 2014, 08:57
Не, echo-то дава съдържението (link text), а не самия линк. Единственият вариант, до който съм стигнал е с ""Inspect element" или както се казва в конкретния браузър, но това, според мен, е по-скоро е за „фина настройка“, а не за постоянно тестване.


Титла: Re: Некоректно сортиране в PHP
Публикувано от: kifavi8024 в Apr 23, 2014, 09:49
Ама гледай сега - нали си даваш сметка, че PHP връща към браузъра HTML. Затова и браузъра го форматира, а за да видиш сорс кода ти трябва да ползваш инструментите на браузъра.

Ако толкова искаш да ти се видиш html кода като нормален текст, може да ползваш нещо от този род:

Код
GeSHi (PHP):
  1. echo '<pre>';
  2. echo htmlspecialchars($YOUR_HTML);
  3. echo '</pre>';[code]


Титла: Re: Некоректно сортиране в PHP
Публикувано от: angie_bg в Apr 23, 2014, 10:13
@Intel, давам си сметка, ама сега, а не когато пуснах темата. Изобщо не се сетих за специалните символи  ??? С тях получавам точно това, което ми трябваше, за да икономисам малко нерви.
Код:
<a href="index.php?page=composers&composer_id=1">Верди, Джузепе</a>; <a href="index.php?page=composers&composer_id=5">Verdi, Giuseppe</a>	Аида
<a href="index.php?page=composers&composer_id=2">Бетовен, Лудвиг ван</a>; <a href="index.php?page=composers&composer_id=4">Стравински, Игор</a> Симфоничен концерт
<a href="index.php?page=composers&composer_id=3">Лист, Ференц</a> Ноктюрно
<a href="index.php?page=composers&composer_id=4">Стравински, Игор</a> Le Sacre du printemps
<a href="index.php?page=composers&composer_id=1">Верди, Джузепе</a>; <a href="index.php?page=composers&composer_id=5">Verdi, Giuseppe</a> La Traviata
<a href="index.php?page=composers&composer_id=6">Атанасов, Маестро Георги</a>
Благодаря още веднъж!  [_]3