Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Сортировка массива по определенным ключам другого массива
Форумы портала PHP.SU » » Вопросы новичков » Сортировка массива по определенным ключам другого массива

Страниц (1): [1]
 

1. antobra - 19 Апреля, 2019 - 11:21:38 - перейти к сообщению
Коллеги, подскажите, пожайлуста, "красивое" решение следующей задачи, до которой не могу дойти самостоятельно.

Имеем большой массив с множеством ключей и значений:

PHP:
скопировать код в буфер обмена
  1. $array = [
  2.  
  3.         'key1' => [ 'somevalue' => 'somevalue', 'type' => 'red' ],
  4.         'key2' => [ 'somevalue' => 'somevalue', 'type' => 'pink' ],
  5.         'key3' => [ 'somevalue' => 'somevalue', 'type' => 'red' ],
  6.         'key4' => [ 'somevalue' => 'somevalue', 'type' => 'pink' ],
  7.         'key5' => [ 'somevalue' => 'somevalue', 'type' => 'white' ],
  8.         'key6' => [ 'somevalue' => 'somevalue', 'type' => 'blue' ],
  9.  
  10. ];
  11.  

Имеем правила сортировки, которые говорят в каком порядке должен быть $array по ключу 'type'.

PHP:
скопировать код в буфер обмена
  1. $rules = [
  2.  
  3.         'blue',
  4.         'red',
  5.         'pink'
  6.  
  7. ];


Таким образом необходимо получить:

PHP:
скопировать код в буфер обмена
  1. $array = [
  2.  
  3.         'key6' => [ 'somevalue' => 'somevalue', 'type' => 'blue' ],
  4.         'key1' => [ 'somevalue' => 'somevalue', 'type' => 'red' ],
  5.         'key3' => [ 'somevalue' => 'somevalue', 'type' => 'red' ],
  6.         'key2' => [ 'somevalue' => 'somevalue', 'type' => 'pink' ],
  7.         'key4' => [ 'somevalue' => 'somevalue', 'type' => 'pink' ],
  8.         'key5' => [ 'somevalue' => 'somevalue', 'type' => 'white' ],
  9.        
  10.  
  11. ];


Если в rules нет ключа, который есть в $array (например, white), то он помещается в конец.

Буду благодарен за помощь
2. lastdays - 19 Апреля, 2019 - 14:18:07 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1.  
  2. function arr_sort( $l, $r )
  3. {
  4.  
  5.        $index = array
  6.        (
  7.         'blue'  => 3,
  8.         'red'   => 2,
  9.         'pink'  => 1
  10.        );
  11.  
  12.        //- Если пусто - в конец.
  13.        if ( empty( $index[$l["type"]] ) )
  14.        {
  15.          $index[$l["type"]] = 0;
  16.        }
  17.  
  18.        //- Если пусто - в конец.
  19.        if ( empty( $index[$r["type"]] ) )
  20.        {
  21.          $index[$r["type"]] = 0;
  22.        }
  23.  
  24.        if ( $index[$l["type"]] < $index[$r["type"]] )
  25.        {
  26.          return true;
  27.        }
  28.        else if ( $index[$l["type"]] > $index[$r["type"]] )
  29.        {
  30.          return false;
  31.        }
  32.  
  33. }
  34.  
  35.  
  36. $arr = array();
  37. $arr['key1'] = array( 'somevalue' => 'somevalue', 'type' => 'white' );
  38. $arr['key2'] = array( 'somevalue' => 'somevalue', 'type' => 'blue' );
  39. $arr['key3'] = array( 'somevalue' => 'somevalue', 'type' => 'red' );
  40. $arr['key4'] = array( 'somevalue' => 'somevalue', 'type' => 'blue' );
  41. $arr['key5'] = array( 'somevalue' => 'somevalue', 'type' => 'red' );
  42. $arr['key6'] = array( 'somevalue' => 'somevalue', 'type' => 'red' );
  43. $arr['key7'] = array( 'somevalue' => 'somevalue', 'type' => 'white' );
  44. $arr['key8'] = array( 'somevalue' => 'somevalue', 'type' => 'red' );
  45.  
  46.  
  47. if ( !empty ( $arr ) )
  48. {
  49.   usort ($arr, 'arr_sort');
  50.  
  51.   foreach ( $arr as $k => $v )
  52.   {
  53.     echo ' '.$k.' => '.$v['type'].' <br />';
  54.   }
  55.   unset( $k, $v );
  56.  
  57. }
  58.  
  59. unset( $arr );
  60.  


Такой вот быдлокод, может кто лучше предложит.
3. Мелкий - 19 Апреля, 2019 - 15:29:06 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1. uasort($array, function($a, $b) use($rules) {
  2.     $apos = array_search($a['type'], $rules);
  3.     $bpos = array_search($b['type'], $rules);
  4.     if ($apos !== false and $bpos !== false)
  5.         return $apos <=> $bpos;
  6.     else
  7.         return ($apos === false) <=> ($bpos === false);
  8. });
  9. var_dump($array);

php 7.0+
Имеет смысл переформатировать $rules во что-то более подходящее для поиска по значению.
(Добавление)
Мелкий пишет:
переформатировать $rules во что-то более подходящее для поиска по значению.

как-то так:
PHP:
скопировать код в буфер обмена
  1. $sortIndex = array_flip($rules);
  2. uasort($array, function($a, $b) use($sortIndex) {
  3.     $apos = $sortIndex[ $a['type'] ] ?? false;
  4.     $bpos = $sortIndex[ $b['type'] ] ?? false;
  5.     if ($apos !== false and $bpos !== false)
  6.         return $apos <=> $bpos;
  7.     else
  8.         return ($apos === false) <=> ($bpos === false);
  9. });
4. LIME - 20 Апреля, 2019 - 13:03:31 - перейти к сообщению
Мелкий дополню для таксказать синьоров
ты же знаешь что сорт реализован как quicksort?
супер что ты учел отсутствие ключа
но...тогда надо отталкиваться от предметной области
если высока вероятность многих таких значений...лучше один раз фулскан с выборкой их
сорт выдохнет облегченно
просто заметил))
5. antobra - 15 Мая, 2019 - 22:44:09 - перейти к сообщению
Коллеги, огромное спасибо. Поблагодарил через "Спасибо!" всех причастных!)

 

Powered by ExBB FM 1.0 RC1