#php #arrays #php-7
#php #массивы #многомерный массив #сумма #группировка
Вопрос:
Мне нужно добавить новые элементы в мой массив, когда встречается новое category
значение. Когда category
значение встречается после первого раза, его value1
и value2
значения должны быть добавлены к соответствующим значениям первого столкновения.
Кроме того, в результирующем массиве я больше не хочу сохранять category
столбец. Строки группировки категорий должны использовать category
значение в качестве своего name
значения.
Пример ввода:
$datas = [
[
'category' => 'Solution',
'name' => 'Name1',
'value1' => 20,
'value2' => 21
],
[
'category' => 'Solution',
'name' => 'Name2',
'value1' => 30,
'value2' => 31
],
[
'category' => 'Solution1',
'name' => 'Name3',
'value1' => 40,
'value2' => 41
]
];
Желаемый результат:
[
['name' => 'Solution', 'value1' => 50, 'value2' => 52],
['name' => 'Name1', 'value1' => 20, 'value2' => 21],
['name' => 'Name2', 'value1' => 30, 'value2' => 31],
['name' => 'Solution1', 'value1' => 40, 'value2' => 41],
['name' => 'Name3', 'value1' => 40, 'value2' => 41]
]
Я пробовал так:
private function groupByProductSuperCategory($datas)
{
$return = [];
foreach ($datas as $data) {
$return[$data['category']][$data['name']] = array_sum(array_column('category', $data);
}
return $return;
}
Идея состоит в том, чтобы сначала вычислить все значения суммы для по категориям, а после этого просто поместить значения из name, как в другой массив. У вас есть идея, как это сделать?
Комментарии:
1. Ваш вывод, похоже, не очень хорошо структурирован. Может быть, поместить их в другой массив, который дает вам информацию о сумме?
2. происходят ли эти данные из базы данных SQL? Если это так, вам, вероятно, было бы лучше написать SQL-запрос, который выдаст вам СУММУ данных, и использовать это вместо этого.
Ответ №1:
Из опубликованного массива… Чтобы получить желаемый массив, сначала нужно выполнить несколько небольших исправлений. Но я предположил, что это было из-за опечаток при копировании здесь…
Итак, вот массив, с которого я начал:
$result = [
0 => [
"category" => 'Solution',
"name" => 'Name1',
"value1" => 20,
"value2" => 21
],
1 => [
"category" => 'Solution',
"name" => 'Name2',
"value1" => 30,
"value2" => 31
],
2 => [
"category" => 'Solution1',
"name" => 'Name3',
"value1" => 40,
"value2" => 41
]
];
Теперь эта реорганизация данных немного сложнее, чем кажется… Вам нужно выполнить несколько циклов, чтобы:
- Найдите разные названия «категории»
- Выполните суммирование для каждого
- Добавьте элемент sum и отдельные элементы
Итак, вот код, которым я закончил:
function groupByProductSuperCategory($datas){
$category = [];
$return = [];
// Find distinct categories
foreach ($datas as $data) {
if(!in_array($data["category"],$category)){
array_push($category,$data["category"]);
}
}
// For each distinct category, add the sum item and the single items
foreach ($category as $cat) {
// Get the sums
if(!in_array($cat,$return)){
$sum1 = 0;
$sum2 = 0;
foreach ($datas as $data) {
if($data["category"] == $cat){
$sum1 = $data["value1"];
$sum2 = $data["value2"];
}
}
}
// Push the sums in the return array
array_push($return,[
"name" => $cat,
"value1" => $sum1,
"value2" => $sum2,
]);
// Push the single elements
foreach ($datas as $data) {
if($cat == $data["category"]){
array_push($return,[
"name" => $data["name"],
"value1" => $data["value1"],
"value2" => $data["value2"],
]);
}
}
}
return $return;
}
Вот PHPFiddle, чтобы попробовать это… Нажмите [F9] для запуска.
Ответ №2:
Гораздо проще, эффективнее и удобочитаемее реализовать единый цикл и поместить ссылочные переменные в результирующий массив, чтобы разрешить суммирование на основе общих категорий без отслеживания фактических индексов строк категорий.
Код: (демо)
$result = [];
foreach ($array as $row) {
if (!isset($ref[$row['category']])) {
$ref[$row['category']] = [
'name' => $row['category'],
'value1' => 0,
'value2' => 0
];
$result[] = amp;$ref[$row['category']];
}
$ref[$row['category']]['value1'] = $row['value1'];
$ref[$row['category']]['value2'] = $row['value2'];
unset($row['category']);
$result[] = $row;
}
var_export($result);