Используя 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
]
]
Я не знаю, как:
Мой текущий код выглядит так:
// 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
$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
);
@SheldonScott Добро пожаловать! Следует отметить, что если у объекта есть несколько дефисов, таких как Bio-Science-3-2 или что-то в этом роде, использование explode('-', $v[0])[0] не будет идеальным, и потребуется добавить дополнительную логику обработки.
Как мне отсортировать массив в порядке убывания? (В настоящее время он находится в порядке возрастания.)
@SheldonScott Не могли бы вы определить «нисходящий», пожалуйста? Какие критерии ставят один предмет перед другим? Если хотите, укажите в первом вопросе пример желаемого порядка сортировки.
Я добавил это в ОП. Спасибо!
@SheldonScott Я не совсем понимаю обновленные критерии. В вашем комментарии здесь вы просите «по убыванию» (по убыванию), но ваш обновленный вопрос, похоже, требует «восходящего» (от низкого к высокому) на основе count? Если можете, предоставьте примерный массив ожидаемого порядка сортировки.
@SheldonScott привет?
Извини - не было на мгновение. При обновлении OP я понял, что он должен быть восходящим, а не нисходящим. Не обращайте внимания на «нисходящую» часть моего комментария выше и замените ее на «по возрастанию».
С этим вы абсолютный ниндзя! Большое спасибо!
@SheldonScott Ха-ха, спасибо! Научиться перемещаться по массивам и манипулировать ими, возможно, оказало наибольшее положительное влияние на достижение элегантных решений, поэтому я рад, что могу поделиться с другими.
Хочу добавить альтернативный подход. Важные заметки:
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'];
});
Не надо впихивать это решение в мой код. Большое спасибо за четкий ответ!