Реструктуризация многомерного массива PHP, использующего array_count_values ​​и array_map

Используя Laravel 5.6, я создаю многомерный массив, который выглядит так:

array:8 [   
    0 => array:2 [
        0 => "ELA-2"
        1 => 7   
    ]   
    1 => array:2 [
        0 => "Science-3"
        1 => 9   
    ]   
    2 => array:2 [
        0 => "ELA-1"
        1 => 5   
    ]   
    3 => array:2 [
        0 => "Science-2"
        1 => 9
    ]   
    4 => array:2 [
        0 => "ELA-4"
        1 => 2   
    ]   
    5 => array:2 [
        0 => "ELA-3"
        1 => 7   
    ]   
    6 => array:2 [
        0 => "Science-4"
        1 => 2   
    ]   
    7 => array:2 [
        0 => "Science-1"
        1 => 1   
    ] 
]

Это было создано с использованием array_count_values ​​и array_map (если это имеет значение).

Я хочу, чтобы данные выглядели так:

array:8 [   
    0 => array:3 [
        "Subject" => "ELA"
        "Level" => 2
        "Count" => 7   
    ]   
    1 => array:3 [
        "Subject" => "Science"
        "Level" => 3
        "Count" => 9 
    ]   
    2 => array:3 [
        "Subject" => "ELA"
        "Level" => 1
        "Count" => 5 
    ]   
    3 => array:3 [
        "Subject" => "Science"
        "Level" => 2
        "Count" => 9
    ]   
    4 => array:3 [
        "Subject" => "ELA"
        "Level" => 4
        "Count" => 2   
    ]   
    5 => array:3 [
        "Subject" => "ELA"
        "Level" => 3
        "Count" => 7  
    ]   
    6 => array:3 [
        "Subject" => "Science"
        "Level" => 4
        "Count" => 2   
    ]   
    7 => array:3 [
        "Subject" => "Science"
        "Level" => 1
        "Count" => 1  
    ] 
]

Я не знаю, как:

  1. разделите значения из ключа [0] в каждом массиве и разделите их на 2 части - первая часть для «Тема» и вторая часть для «Уровня».
  2. измените метку цифровых клавиш увеличения (в каждом массиве их будет по 3) на слова «Тема», «Уровень» и «Счетчик» соответственно.

Мой текущий код выглядит так:

// create an empty array
$array_holder = [];

// loop through each student
foreach($class_students as $student) {

    // loop through each subject
    foreach($class_subjects as $subject) {

        // count each child at his/her level (rounded average)
        $childs_level = AssessmentData::where('student_id', $student->id)->where('subject_id', $subject->subject_id)->avg('assessed_level');

        // get the subject name
        $current_subject = Subject::where('id', $subject->subject_id)->first();

        // round the average
        $childs_level = round($childs_level);

        // convert the childs_level into a whole number
        $childs_level = number_format($childs_level, 0);

        // add each child by appending to an array
        if ($childs_level != 0) {
            $compiled_array[] = array_push($array_holder, $current_subject->short_name."-".$childs_level);
        }
    }
}

// count each assessed_level from the resultant array
$counted_array = array_count_values($array_holder);

// remap the array
$counted_array = array_map(null, array_keys($counted_array), $counted_array);

Дополнительный запрос - сортировка

Я хотел бы, чтобы результаты были отсортированы по количеству, чтобы уровень 1 был первым, уровень 2 был вторым, уровень 3 был третьим, а уровень 4 был четвертым. (В настоящее время он отсортирован в обратном порядке - уровень 4 - первый, уровень 3 - второй и т. д.)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
199
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам нужно зациклить исходный массив и создать новый:

<?php
$original_array = [
    ['ELA-2', 7],
    ['Science-3', 9],
    ['ELA-1', 5]
    // you can fill in the rest
];

$new_array = [];
foreach($original_array as $v)
{
    $new_array[] = [
        'Subject' => explode('-', $v[0])[0], // split the subject on "-" and retrieve the first item
        'Level' => explode('-', $v[0])[1], // split the subject on "-" and retrieve the second item
        'Count' => $v[1] // this is given to us so just use it
    ];
}

// Sort the finished product in ascending order based on the "count" of the sub-arrays
//
// You can also use this earlier on $original_array if you want
// but you would just change the arithmetic to $a[ 1 ] - $b [ 1 ]
usort( $new_array, function( $a, $b ){
    return $a[ 'Count' ] - $b[ 'Count' ];
} );

print_r($new_array);

Выход:

Array
(
    [0] => Array
        (
            [Subject] => ELA
            [Level] => 1
            [Count] => 5
        )

    [1] => Array
        (
            [Subject] => ELA
            [Level] => 2
            [Count] => 7
        )

    [2] => Array
        (
            [Subject] => Science
            [Level] => 3
            [Count] => 9
        )

)

Если вы хотите получить фантазию и array_map(), то это дает тот же результат, что и foreach(){}:

$new_array = array_map(
    function($v){
        return [
            'Subject' => explode('-', $v[0])[0], // split the subject on "-" and retrieve the first item
            'Level' => explode('-', $v[0])[1], // split the subject on "-" and retrieve the second item
            'Count' => $v[1] // this is given to us so just use it
        ];
    },
    $original_array
);

Не надо впихивать это решение в мой код. Большое спасибо за четкий ответ!

Sheldon Scott 03.05.2018 16:06

@SheldonScott Добро пожаловать! Следует отметить, что если у объекта есть несколько дефисов, таких как Bio-Science-3-2 или что-то в этом роде, использование explode('-', $v[0])[0] не будет идеальным, и потребуется добавить дополнительную логику обработки.

MonkeyZeus 03.05.2018 16:32

Как мне отсортировать массив в порядке убывания? (В настоящее время он находится в порядке возрастания.)

Sheldon Scott 04.05.2018 16:28

@SheldonScott Не могли бы вы определить «нисходящий», пожалуйста? Какие критерии ставят один предмет перед другим? Если хотите, укажите в первом вопросе пример желаемого порядка сортировки.

MonkeyZeus 04.05.2018 16:31

Я добавил это в ОП. Спасибо!

Sheldon Scott 04.05.2018 16:39

@SheldonScott Я не совсем понимаю обновленные критерии. В вашем комментарии здесь вы просите «по убыванию» (по убыванию), но ваш обновленный вопрос, похоже, требует «восходящего» (от низкого к высокому) на основе count? Если можете, предоставьте примерный массив ожидаемого порядка сортировки.

MonkeyZeus 04.05.2018 16:45

@SheldonScott привет?

MonkeyZeus 04.05.2018 16:57

Извини - не было на мгновение. При обновлении OP я понял, что он должен быть восходящим, а не нисходящим. Не обращайте внимания на «нисходящую» часть моего комментария выше и замените ее на «по возрастанию».

Sheldon Scott 04.05.2018 17:05

С этим вы абсолютный ниндзя! Большое спасибо!

Sheldon Scott 04.05.2018 17:19

@SheldonScott Ха-ха, спасибо! Научиться перемещаться по массивам и манипулировать ими, возможно, оказало наибольшее положительное влияние на достижение элегантных решений, поэтому я рад, что могу поделиться с другими.

MonkeyZeus 04.05.2018 17:23

Хочу добавить альтернативный подход. Важные заметки:

  • не просите PHP выполнить один и тот же вызов explode() для одной и той же строки дважды - кешируйте ее как временную переменную или, как показано в моем фрагменте, используйте все сгенерированные элементы сразу.
  • ограничьте свой вызов explode(), объявив параметр limit (3-й параметр), чтобы выходные данные были согласованными, а сценарий четко понимал предполагаемое действие (просмотр входных данных не требуется для понимания намерения).
  • оператор космического корабля в usort() очень универсален и позволит вам проводить различные сравнения без изменения синтаксиса.

Код: (Демо)

$counted_array = [
    ["ELA-2", 7], 
    ["Science-3", 9],
    ["ELA-1", 5],
    ["Science-2", 9],
    ["ELA-4", 2], 
    ["ELA-3", 7],
    ["Science-4", 2], 
    ["Science-1", 1]
];

$assoc_array = array_map(
    function($subarray){
        return array_combine(
                   ['Subject', 'Level'], explode('-', $subarray[0], 2)
               )
               + ['Count' => $subarray[1]];
    },
    $counted_array
);

usort($assoc_array, function($a, $b) {
    return [$a['Subject'], $a['Level']]
           <=>
           [$b['Subject'], $b['Level']];
});

var_export($assoc_array);

Я заметил, что в вашем вопросе вы запросили сортировку данных по Count, но затем продолжили объяснять, как вы ожидали сортировки по уровню - это неоднозначно.

Если вы хотите отсортировать по графу, просто используйте:

usort($assoc_array, function($a, $b) {
    return $a['Count'] <=> $b['Count'];
});

Другие вопросы по теме