За последние 24 часа нас посетили 22867 программистов и 1238 роботов. Сейчас ищут 732 программиста ...

Сортировка многомерного массива по ключу

Тема в разделе "PHP для новичков", создана пользователем lastdays, 1 апр 2020.

  1. lastdays

    lastdays Активный пользователь

    С нами с:
    27 сен 2012
    Сообщения:
    410
    Симпатии:
    74
    Привет!

    Есть массив:
    PHP:
    1. $teams[] = array( 'name' => 'Василий', 'age' => 17 );
    2. $teams[] = array( 'name' => 'Владимир', 'age' => 16 );
    3. $teams[] = array( 'name' => 'Анастасия', 'age' => 15 );
    4. $teams[] = array( 'name' => 'Александр', 'age' => 16 );

    Данные в массиве (возраст) практически всегда разный.
    Как правильно отсортировать массив по age, но при этом равномерно (или почти) распределить по двум сторонам(командам) ?
    Чтобы вышло:
    Первая команда age 17 + 15 ( суммарно 32 года )
    Вторая команда age 16 + 16 ( суммарно 32 года )
    * Важно, чтобы возраст первой команды не очень сильно превышал возраст второй


    Действующий пример БЕЗ сортировки по age
    PHP:
    1. shuffle($teams);
    2.  
    3. $c_1 = array();
    4. $c_2 = array();
    5.  
    6. for ( $i = 0; $i < sizeOf($teams); $i++)
    7. {
    8.   if ( isset ($teams[$i] ) )
    9.   {
    10.    if ($i%2==0) $c_1[] = $teams[$i]; else $c_2[] = $teams[$i];
    11.   }
    12. }
    13.  
    14. var_dump($c_1);
    15. var_dump($c_2);
    p.s. Сортировку по age с помощью функции usort вышло сделать, но это мало что изменило.
    Просто распределяю по очереди, 17 в первую, 17 во вторую и так далее.

    PHP:
    1. usort($teams, function($x, $y)
    2. {
    3.  return mt_rand(1,2) == 1 ? ( $x["age"] > $y["age"] ? 1 : ($x["age"] < $y["age"] ? -1 : 0) ) : ( $x["age"] > $y["age"] ? 1 : ($x["age"] < $y["age"] ? -1 : 0) );
    4. });

    С таким раньше не приходилось сталкиваться.
    Спасибо за возможную помощь и внимание.
     
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.752
    Симпатии:
    1.322
    Адрес:
    Лень
    https://php.ru/forum/search/2125212/?q=Сортировка+многомерного+массива+по+ключу&o=date
    --- Добавлено ---
    а.. 6ля
     
  3. lastdays

    lastdays Активный пользователь

    С нами с:
    27 сен 2012
    Сообщения:
    410
    Симпатии:
    74
    Да сортировать не проблема, можно решить.
    Если что, готов на международную карту сотню другую рублей дать за реализацию.
     
  4. Sail

    Sail Старожил

    С нами с:
    1 ноя 2016
    Сообщения:
    1.591
    Симпатии:
    360
    @lastdays, глянь способ.
     
    lastdays нравится это.
  5. Valick

    Valick Активный пользователь

    С нами с:
    12 авг 2018
    Сообщения:
    1.911
    Симпатии:
    328
    @Sail, при таком алгоритме может получится разное количество человек в командах.
     
  6. brevis

    brevis Активный пользователь

    С нами с:
    23 июл 2019
    Сообщения:
    69
    Симпатии:
    20
  7. lastdays

    lastdays Активный пользователь

    С нами с:
    27 сен 2012
    Сообщения:
    410
    Симпатии:
    74
    Спасибо за отклик!

    Приведу второй пример ( близок к истине )

    PHP:
    1. $teams = array();
    2. $teams[] = array( 'name' => 'Имя 5', 'age' => 14 );
    3. $teams[] = array( 'name' => 'Имя 4', 'age' => 10 );
    4. $teams[] = array( 'name' => 'Имя 1', 'age' => 12 );
    5. $teams[] = array( 'name' => 'Имя 3', 'age' => 9 );
    6. $teams[] = array( 'name' => 'Имя 2', 'age' => 13 );
    7. $teams[] = array( 'name' => 'Имя 6', 'age' => 12 );
    8.  
    9. //- Сортируем по убыванию
    10. usort($teams, function($x, $y)
    11. {
    12. return ( $x["age"] < $y["age"] ? 1 : ($x["age"] > $y["age"] ? -1 : 0) ) ;
    13. });
    14.  
    15. //- Половина от всей суммы
    16. $half_summ = intval( array_sum( array_map( function($element){ return $element['age']; }, $teams) ) / 2 );
    17.  
    18. //- Группа 1
    19. $c_1 = array();
    20. //- Группа 2
    21. $c_2 = array();
    22.  
    23. //- Сумма группы 1
    24. $summ_1 = 0;
    25. //- Сумма группы 2
    26. $summ_2 = 0;
    27.  
    28. //- Перебираем отсортированный массив
    29. foreach ( $teams as $key => $val )
    30. {
    31.     if($summ_1 <= $summ_2 OR $summ_2 >= $half_summ )
    32.     {
    33.         $c_1[] = $teams[$key];
    34.         $summ_1 += $val['age'];
    35.     }
    36.     else
    37.     {
    38.         $c_2[] = $teams[$key];
    39.         $summ_2 += $val['age'];
    40.     }
    41. }
    42. unset( $teams, $key, $val );
    43.  
    44. var_dump($c_1);
    45. echo $summ_1;
    46.  
    47. echo '<hr>';
    48.  
    49. var_dump($c_2);
    50. echo $summ_2;
    Но при такой сортировке всегда одни и те же лица в первой и второй группе. Немного не то, к сожалению :(
     
  8. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.266
    Симпатии:
    405
    А если так, но людей надо побольше чтобы было видно разницу
    PHP:
    1. <?php
    2. $teams = array();
    3. $teams[] = array( 'name' => 'Имя 5', 'age' => 14 );
    4. $teams[] = array( 'name' => 'Имя 4', 'age' => 10 );
    5. $teams[] = array( 'name' => 'Имя 1', 'age' => 12 );
    6. $teams[] = array( 'name' => 'Имя 3', 'age' => 9 );
    7. $teams[] = array( 'name' => 'Имя 2', 'age' => 13 );
    8. $teams[] = array( 'name' => 'Имя 6', 'age' => 12 );
    9.  
    10. $count = count($teams);
    11. $numbers = range(0, $count-1);
    12. shuffle($numbers);
    13. $array = [];
    14.  
    15. foreach ($numbers as $n) {
    16.     $array[] = $teams[$n];
    17. }
    18.  
    19. usort($array, function($x, $y)
    20. {
    21. return ( $x["age"] < $y["age"] ? 1 : ($x["age"] > $y["age"] ? -1 : 0) ) ;
    22. });
    23. //- Половина от всей суммы
    24. $half_summ = intval( array_sum( array_map( function($element){ return $element['age']; }, $teams) ) / 2 );
    25. //- Группа 1
    26. $c_1 = array();
    27. //- Группа 2
    28. $c_2 = array();
    29. //- Сумма группы 1
    30. $summ_1 = 0;
    31. //- Сумма группы 2
    32. $summ_2 = 0;
    33. //- Перебираем отсортированный массив
    34. foreach ( $array as $key => $val )
    35. {
    36.     if($summ_1 <= $summ_2 OR $summ_2 >= $half_summ )
    37.     {
    38.         $c_1[] = $array[$key];
    39.         $summ_1 += $val['age'];
    40.     }
    41.     else
    42.     {
    43.         $c_2[] = $array[$key];
    44.         $summ_2 += $val['age'];
    45.     }
    46. }
    47. unset( $array, $key, $val );
    48. var_dump($c_1);
    49. echo $summ_1;
    50. echo '<hr>';
    51. var_dump($c_2);
    52. echo $summ_2;