Добавить элементы группировки в 2d-массив и суммировать значения в соответствующей группе

#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);