Как отсортировать ассоциативный массив на основе конкретного ключа?

Я пробовал много трюков и googling, чтобы решить эту проблему, но не мог получить полезный материал.

В основном следует содержание элемента из ассоциативного массива (результат экзамена кандидатов, и я должен дать рейтинг кандидатам), который содержит несколько таких элементов.

Я хочу сортировать массив в порядке возрастания, в зависимости от ключа [total_obtained_marks] , то есть кандидата, имеющего больше меток, будет первым ранжироваться,

то если такие же значения обнаруживают, что я должен сортировать массив в порядке убывания на основе ключа [no_wrong_answers] i.e. less no. неправильных ответов.

Даже если ранг остается таким же, я должен сортировать массив в порядке возрастания ключа [test_user_time_used] , то есть кандидат с меньшим временем использования получит более высокий ранг.

Даже тогда ранги одинаковы, тогда я должен отсортировать массив на ключе [user_first_name] в порядке возрастания по алфавиту.

После выполнения всего этого я мог бы получить отсортированный массив, который будет иметь правильный рейтинг для кандидатов.

Еще одна вещь об этом несортированном массиве - фактические данные не могут быть отсортированы из базы данных, поэтому функции базы данных не могут использоваться.

Все, что должно быть сделано, будет на этом несортированном массиве. Пожалуйста, помогите мне решить эту проблему. Заранее спасибо. Имя ассоциативного массива - $ test_result .

Array
(
    [14ddcea23dfc46bed4f2a15da7901c51] => Array
        (
            [test_user_data] => Array
                (
                    [test_user_id] => 6297
                    [test_user_user_id] => 14ddcea23dfc46bed4f2a15da7901c51
                    [test_user_test_id] => 348
                    [user_first_name] => Shahin
                    [user_last_name] => Khan
                    [user_name] => Shahin Khan
                    [test_user_status] => present
                    [test_user_time_used] => 00:00:00 Hr
                    [test_user_start_time] => 1356514472
                    [test_duration] => 4500
                    [test_name] => NEET: Electrostatics 1
                    [test_mode] => non-schedule
                    [test_end_time] => 0
                    [user_status] => Attempted
                )

            [test_question_data] => Array
                (
                    [73101] => Array
                        (
                            [question_text] => If a glass rod is rubbed with silk it acquires a positive charge because :
                            [question_file] => 
                            [correct_ans_text] => electrons are removed from it
                            [correct_ans_file] => 
                            [correct_ans_id] => 291299
                            [user_marked_ans_text] => electrons are removed from it
                            [user_marked_ans_file] => 
                            [user_marked_ans_id] => 291299
                        )

                    [77101] => Array
                        (
                            [question_text] => In a charged capacitor , the energy is stored in :
                            [question_file] => 
                            [correct_ans_text] => the field between the plates
                            [correct_ans_file] => 
                            [correct_ans_id] => 307468
                            [user_marked_ans_text] => the field between the plates
                            [user_marked_ans_file] => 
                            [user_marked_ans_id] => 307468
                        )

                    [75069] => Array
                        (
                            [question_text] => ABC is right-angle triangle with sides AB = 3 cm, BC = 4 cm, AC = 5 cm, charges 15, 12 and -20 respectively. Magnitude of the force experienced by the charge at B in dynes is :
\"\" [question_file] =>  [correct_ans_text] => 25 [correct_ans_file] =>  [correct_ans_id] => 299192 [user_marked_ans_text] => 25 [user_marked_ans_file] =>  [user_marked_ans_id] => 299192 ) [77526] => Array ( [question_text] => The work done in increasing the coltage across the plates of a capacitor from 5 V to 10 V is W. The work done in increasing the voltage from 10 V to 15 V will be : [question_file] =>  [correct_ans_text] => W [correct_ans_file] =>  [correct_ans_id] => 578079 [user_marked_ans_text] => W [user_marked_ans_file] =>  [user_marked_ans_id] => 578079 ) [73190] => Array ( [question_text] => Select the corrent alternative : [question_file] =>  [correct_ans_text] => Charge cannot exist without matter although matter can exist without charge [correct_ans_file] =>  [correct_ans_id] => 291651 [user_marked_ans_text] => Charge cannot exist without matter although matter can exist without charge [user_marked_ans_file] =>  [user_marked_ans_id] => 291651 ) [127452] => Array ( [question_text] => Capacity of a conductor depends upon [question_file] =>  [correct_ans_text] => size of conductor
[correct_ans_file] =>  [correct_ans_id] => 510229 [user_marked_ans_text] => all of these
[user_marked_ans_file] =>  [user_marked_ans_id] => 510232 ) [127503] => Array ( [question_text] => A charged spherical shell does not produce an electric field at any [question_file] =>  [correct_ans_text] => interior point
[correct_ans_file] =>  [correct_ans_id] => 510425 [user_marked_ans_text] => interior point
[user_marked_ans_file] =>  [user_marked_ans_id] => 510425 ) [75631] => Array ( [question_text] => A solid conducting sphere having a charge Q is surrounded by an uncharged concentric conducting hollow spherical shell. Let the potential difference between the surface of the solid sphere and that of the outer surface of the hollow shell be V . If the shell is now given a charge -3q , the new potential difference between the same two surface is : [question_file] =>  [correct_ans_text] => V [correct_ans_file] =>  [correct_ans_id] => 301488 [user_marked_ans_text] =>  [user_marked_ans_file] =>  [user_marked_ans_id] =>  ) ) [subject_wise_result] => Array ( [5] => Array ( [subject_id] => 5 [subject_name] => 12 PHYSICS [no_correct_answers] => 6 [no_wrong_answers] => 1 [no_skipped_questions] => 38 [total_obtained_marks] => 23 [total_questions] => 45 [total_percent] => 100 % [gain_percent] => 12.78 %  ) ) [test_result_data] => Array ( [no_correct_answers] => 6 [no_wrong_answers] => 1 [no_skipped_questions] => 38 [total_obtained_marks] => 23 ) ) )
1
nl ja de
Также дубликат PHP "> stackoverflow.com/questions/2978447/… , stackoverflow.com/questions/ 7239783/array-sorting-in-php , stackoverflow.com/questions/5200385/sort- array-in-php и в основном все вопросы в поиске "php sort array of массивы ".
добавлено автор Niet the Dark Absol, источник
возможный дубликат PHP сортирует массив массива
добавлено автор Niet the Dark Absol, источник
@JonStirling. Я новичок в PHP. Я использовал функцию print_r (), чтобы показать массив и поместить содержимое одного из его элементов.
добавлено автор PHPLover, источник
@SDC. По вашему предложению я сделал правильное форматирование. Теперь вы можете получить лучшее представление о сценарии. Спасибо за ваше предложение. Я буду иметь в виду в следующий раз.
добавлено автор PHPLover, источник
@LightnessRacesinOrbit не на SO, в его коде. Единственный способ, которым я знаю, получить вывод print_r() , выглядящий так, как он первоначально разместил его, - вывести его, чтобы выгрузить его в HTML без
 .
добавлено автор Sammitch, источник
Способы получения нечеткого форматирования: 1. Инкапсулируйте вывод print_r() в теги
 . 2. Скопируйте вывод из источника страницы. 3. Запустите его из командной строки.
добавлено автор Sammitch, источник
@Sammitch: Почему HTML
  теги? Мы используем  Markdown  здесь, на SO. Пожалуйста, прочтите FAQ по форматированию.
добавлено автор Lightness Races in Orbit, источник
@Sammitch: Да, правильно. :) Ну, он должен иметь «View Source» d в любом случае.
добавлено автор Lightness Races in Orbit, источник
намного лучше :) (хотя и не уверен, почему это html-encoded, print_r этого не делает). (а также текстовый текст все равно может состоять в разделении на абзацы)
добавлено автор SDC, источник
Весь пост - это один большой отпечаток текста. Это очень трудно читать. Отформатируйте его в параграфы; больше людей потребуется время, чтобы прочитать его, если оно разбито на более мелкие кусочки. А затем для бит print_r() используйте «источник просмотра» и скопируйте + вставить, а не неформатированную версию, показанную в браузере.
добавлено автор SDC, источник
Argh, отформатируйте свои сообщения: |
добавлено автор Jon Stirling, источник

2 ответы

PHP предоставляет довольно много функций для сортировки массивов . В этом случае вы хотите uasort() , который сортирует массив согласно к пользовательской функции сравнения при сохранении ассоциаций ключевых значений:

function compare_results ( $a, $b ) {
    $diff = strcmp( $a['test_user_data']['user_status'],
                    $b['test_user_data']['user_status'] );
    if ( $diff != 0 ) return $diff < 0 ? -1 : 1; //ascending order
   //("Attempted" < "Not attempted")

    $diff = $a['test_result_data']['total_obtained_marks'] -
            $b['test_result_data']['total_obtained_marks'];
    if ( $diff != 0 ) return $diff > 0 ? -1 : 1; //descending order

    $diff = $a['test_result_data']['no_wrong_answers'] -
            $b['test_result_data']['no_wrong_answers'];
    if ( $diff != 0 ) return $diff < 0 ? -1 : 1; //ascending order

    $diff = strcmp( $a['test_user_data']['test_user_time_used'],
                    $b['test_user_data']['test_user_time_used'] );
    if ( $diff != 0 ) return $diff < 0 ? -1 : 1; //ascending order

    $diff = strcmp( $a['test_user_data']['user_name'],
                    $b['test_user_data']['user_name'] );
    if ( $diff != 0 ) return $diff < 0 ? -1 : 1; //ascending order

    return 0; //give up, they're as good as equal
}

uasort( $test_result, compare_results );

Написание таких функций сравнения (кратко) описано на странице usort() .

Note, in particular, the warning about non-integer return values being truncated, which is why I'm returning $diff < 0 ? -1 : 1 rather than just $diff itself. In your case, this shouldn't matter, since the numeric values appear to be integers, but it could cause hard-to-find bugs if the system was ever modified to allow, say, partial marks to be awarded. Thus, always returning either -1, 0 or 1 from comparison functions is a good habit to get into.

(For the string comparisons, the $diff < 0 ? -1 : 1 is doubly pointless, since strcmp() is documented to always return -1, 0 or 1 anyway, but I've used it there also for the sake of consistency. It doesn't really do any harm, and as I said, it's a good habit to get into.)

Также обратите внимание, что я сравниваю значения времени как строки. Если это не дает ожидаемых результатов, вам нужно написать собственный код сравнения времени.

Ps. Если вы используете PHP 5.3.0 или новее, вы также можете написать функцию сравнения как анонимная функция , например:

uasort( $test_result, function ( $a, $b ) {
   //function body goes here
} );
7
добавлено
Большое спасибо @Ilmari Karonen. Изменения, внесенные вами в код, сделали для меня волшебство. Также ваши ценные советы помогли мне получить полностью отсортированный ассоциативный массив. Еще раз спасибо.
добавлено автор PHPLover, источник
У меня небольшая проблема с отсортированным ассоциативным массивом. В ассоциативном массиве имеется несколько элементов, у которых [user_status] имеет значение «Не пыталось», как это [user_status] => Not Tryempted. Я хочу поместить все такие элементы массива в нижней части отсортированного массива после элементов, значение которых [user_status] => Попытка. Какой код следует писать, чтобы сделать отсортированный массив лучше? Может ли кто-нибудь помочь? Заранее спасибо.
добавлено автор PHPLover, источник
Большое вам спасибо Илмари Каронен за понимание и решение моей проблемы. Ваш код сделал требуемую магию, я получил отсортированный массив, как я хотел. Еще раз спасибо за вашу ценную помощь.
добавлено автор PHPLover, источник
Если это единственные возможные значения, вы можете просто отсортировать записи сначала на основе значения user_status . (Я только что отредактировал свой ответ, чтобы сделать это, см. Выше). Если вам нужно что-то более сложное (например, если правила сортировки пользователей «Не пытались» должны отличаться от правил для «Попыток»), то тот же принцип все еще применяется: сначала проверьте, является ли один из $ a и $ b "Not Tryempted", а другой - "Tryempted", и если да, то возвратите -1 или +1 в зависимости от который есть; в противном случае сравните другие поля, если это необходимо.
добавлено автор Ilmari Karonen, источник
Или, альтернативно, вы можете просто сделать две копии массива, удалить пользователей «Не пытайтесь» из одной копии и «Попытка» из другой, используя array_filter() , затем отсортируйте каждую копию отдельно и добавьте их вместе с + или < код> array_merge() .
добавлено автор Ilmari Karonen, источник

Вам нужно определить свою собственную функцию сравнения и отсортировать массив, используя usort() .

function cmp($a, $b) {
    $a = $a['test_result_data']['total_obtained_marks'];
    $b = $b['test_result_data']['total_obtained_marks'];
    if ($a == $b) return 0;
    return ($a < $b ? -1 : 1);
}

usort($array, 'cmp');
0
добавлено
Вы также можете использовать затворы, на что-то приятнее смотреть.
добавлено автор lethal-guitar, источник
phpGeeks
phpGeeks
3 620 участник(ов)

Best PHP chat Еще: @dbGeeks - базы данных @phpGeeksJunior - новичкам @moscowProgers - IT Москва @ebanoePhp - весёлый канал о PHP @laravel_pro - Laravel @jobGeeks - вакансии @jsChat - JS Правила: https://t.me/phpGeeks/764859 ДР - 28.03.2016

PHP
PHP
1 309 участник(ов)

Группа про современный PHP. Обсуждаем ООП, TDD, BDD, DDD, SOLID, GRASP и прочие крутые базворды Для ознакомления: https://gist.github.com/mkusher/711bd46f0b62fbae851182e6fb3b1839 Группа PHP для новичков @phpGeeksJunior Вакансии: https://t.me/fordev

PHP — вакансии, поиск работы и аналитика
PHP — вакансии, поиск работы и аналитика
1 251 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению PHP, Laravel, Symfony, Yii и т.д. Здесь всё: full-time, part-time, remote и разовые подработки. См. также: @qa_jobs, @devops_jobs, @javascript_jobs, @nodejs_jobs, @uiux_jobs, @products_jobs

phpGeeksJunior
phpGeeksJunior
980 участник(ов)

Группа для новичков. Не стесняйтесь задавать вопросы по php. Не флудить!!!! Правила и полезные ссылки https://gist.github.com/exileed/a53dd0617b35a705ff44b38c8028e6a5 Бест от пхпгикс https://t.me/best_of_phpgeeks

phpclub.ru
phpclub.ru
872 участник(ов)

Официальный чат phpclub.ru - остерегайтесь подделок #rules Правила группы - уважайте друг друга. Скриншоты -> ссылками. Код -> pastebin.com. Вакансии строго -> https://goo.gl/4bNxym, в чат ссылку. За рекламу и мат - БАН!

Devall | PHP
Devall | PHP
272 участник(ов)

Пристанище для восходящих звёзд разработки, которые перейдут на более адекватные языки. http://combot.org/chat/-1001014863761 Инвайт: j.mp/devallphp