Требуется отсортировать многомерный массив сложным способом

Тема в разделе "Как сделать...", создана пользователем General Fizz, 5 сен 2009.

Статус темы:
Закрыта.
  1. General Fizz

    General Fizz Боевой Генерал :)

    Регистр.:
    11 апр 2007
    Сообщения:
    753
    Симпатии:
    396
    Задача вроде бы и простая, но тем не менее...
    Имеется массив:
    PHP:
    $mas=array(
      
    'строка2' => array( 712,   321574,  1),
      
    'строка1' => array( 525,    083,  475),
      
    'строка3' => array(6855,  267,  31475),
      
    'строка6' => array(12357545,  0,  7,  2)
      ...
    );

    Нужно его отсортировать по строкам строка1,2,3... таким образом чтобы:
    на первом месте была строка, у которой все значения среди всех пяти числовых параметров максимальны. Вторая строка после первой и так далее.

    Распределенные места для примера выше:
    строка2 - 3,3,2,1,4
    строка1 - 4,4,1,4,1
    строка3 - 1,2,3,2,1
    строка6 - 2,1,4,3,3


    Для данного примера правильный результат будет array('строка3', 'строка6', 'строка2', 'строка1'). Строка6 стоит выше строки2 потому что при одинаковом распределении мест (одно первое, одно второе два третьих и одно четвертое) у строки6 в параметре [0] место второе, а у строки2 третье.

    Числовые значения возвращать не нужно, достаточно только отсортированные строки.

    Строк может быть много, числовых параметров только пять, большинство из них могут быть нулями, но не все.
    Похожая задача - отсортировать страны по количеству полученных медалей на Олимпийских Играх в соотвтетствии с их достоинством, то есть на первом месте страна с наибольшим количеством золотых медалей, потом серебрянных и бронзовых, только в данном случае числовых параметров (достоинств медалей) не 3, а 5.
     
  2. General Fizz

    General Fizz Боевой Генерал :)

    Регистр.:
    11 апр 2007
    Сообщения:
    753
    Симпатии:
    396
    Чтобы было более наглядно, сформулирую задачу таким образом.

    На Олимпийских Играх 2030 года в Бобруйске страны-участники завоевали следующее количество медалей:

    PHP:
    Белоруссия      золотых -  2серебрянных -  3бронзовых -  1оловянных 15деревянных 88;
    Украина         золотых 54серебрянных -  0бронзовых -  8оловянных -  1деревянных -  7;
    Китай           золотых 84серебрянных 22бронзовых -  0оловянных 41деревянных -  0;
    США             золотых 41серебрянных 10бронзовых -  0оловянных -  0деревянных 17;
    Зимбабве        золотых 18серебрянных -  6бронзовых 14оловянных 13деревянных -  8;
    Северная Корея  золотых -  0серебрянных -  5бронзовых -  0оловянных 22деревянных 12;
    Казахстан       золотых 25серебрянных -  0бронзовых -  8оловянных 15деревянных -  0;
    Россия          золотых 98серебрянных -  3бронзовых -  7оловянных -  2деревянных 10;

    Или если представить по-другому:

    PHP:
    $medals=array(

    'Белоруссия'     => array( 2,  3,  11588),
    'Украина'        => array(54,  0,  8,  1,  7),
    'Китай'          => array(8422,  041,  0),
    'США'            => array(4110,  0,  017),
    'Зимбабве'       => array(18,  61413,  8),
    'Северная Корея' => array( 0,  5,  02212),
    'Казахстан'      => array(25,  0,  815,  0),
    'Россия'         => array(98,  3,  7,  210)

    );

    Требуется расставить все страны по максимальному количеству медалей всех проб одновременно, в убывающем порядке. В случае одинакового количества медалей приоритет имеет проба медали.


    Например из двух стран - Китай(84, 22, 0, 41, 0) и Зимбабве(18, 6, 14, 13, 8), Китай должен стоять выше, поскольку он по количеству серебрянных и оловянных медалей имеет первые места, а Зимбабве имеет первое место только по количеству бронзовых медалей.

    Если же допустим у Китая(0, 22, 0, 41, 0), а у Зимбабве(0, 22, 0, 41, 8), то выше должна стоять Зимбабве, поскольку Зимбабве стоит выше Китая по количеству деревянных медалей.


    Занимаемые странами места по количеству медалей одной пробы в соответствии с массивом $medals:
    PHP:
    $medals_positons=array(
    'Белоруссия'     => array( 7,  5,  5,  3,  1),
    'Украина'        => array( 3,  7,  2,  7,  6),
    'Китай'          => array( 2,  1,  6,  1,  7),
    'США'            => array( 4,  2,  6,  8,  2),
    'Зимбабве'       => array( 6,  3,  1,  5,  5),
    'Северная Корея' => array( 8,  4,  6,  2,  3),
    'Казахстан'      => array( 5,  7,  2,  3,  7),
    'Россия'         => array( 1,  5,  4,  6,  4)
    );

    То есть задача состоит в том, чтобы отсортировать массив $medals по убывающей в соответствии с критериями выше.
     
  3. omfg

    omfg

    Регистр.:
    4 авг 2009
    Сообщения:
    159
    Симпатии:
    46
  4. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Что-то во втором твоем посте не только более наглядно, но еще и другая задача, намного проще:

    1) Заведем функцию reduce() для массива с медалями конкретной страны, которая будет возвращать его "вес". Кол-во золотых медалей * миллион + кол-во серебряных * 10 тысяч + кол-во бронзовых * 100 ... и так далее. Весовые коэффициенты расставь сам по вкусу, хочешь - сделай чтоб 10 бронзовых = 1 серебряной, а хочешь - чтоб и миллион бронзовых все равно не "перевешивал" одно серебро. Разница только в соотношении порядков величин, т.е. сколько всего у страны может быть медалей одного типа. На выходе получаем просто число.

    2) Как правильно заметил человек выше, создадим свою функцию сортировки и передадим ее в usort. Функция сортировки простейшая - просто сравниваем "в лоб" два reduce() от аргументов, и какой больше - тот массив и ставим выше в результатах сортировки.
     
  5. General Fizz

    General Fizz Боевой Генерал :)

    Регистр.:
    11 апр 2007
    Сообщения:
    753
    Симпатии:
    396
    Второй пост немного исправил, теперь задача описана точно как и в первом.
     
  6. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Ну то же самое, только весовые коэффициенты у тебя должны быть такие, чтобы 2 бронзовых (и даже две деревянных) перевешивало одну серебрянную, а при равном количестве приоритет отдавался более крутым медалям. И так как количества медалей - целые числа, то разница в коэффициентах должна тогда получается идти на сотые или тысячные, смотря сколько там у тебя этих медалей может максимум быть.

    Т.е. reduce() будет иметь вид
    $golds*1.001 + $silvers*1.00001 + $bronzes * 1.0000001 + $plumbums * 1.000000001 + $woods * 1.00000000001;
    В float влазит без проблем :)
     
    General Fizz нравится это.
Статус темы:
Закрыта.