4

我有一个数组,它是作为来自两个单独数据库的两个数据库查询的组合创建的,它看起来类似于:

$arr1 = [
    ['part' => '1', 'address' => 'aaa', 'type' => '1', 'count' => 5],
    ['part' => '1', 'address' => 'bbb', 'type' => '1', 'count' => 5],
    ['part' => '1', 'address' => 'ccc', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'aaa', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'bbb', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'ccc', 'type' => '2', 'count' => 5]
];

我正在寻找一种方法来按parttype值对这个数组进行分组。我还需要知道count它们被分组时的总和。

结果将类似于:

$arr2 = [
    ['part' => '1', 'type' => '1', 'count' => 15],
    ['part' => '2', 'type' => '1', 'count' => 10],
    ['part' => '2', 'type' => '2', 'count' => 5]
];

但我只是看不到如何做到这一点。我见过一些按单个键/值分组的示例,但不是一次按多个值分组。

4

5 回答 5

9

这个功能应该可以完成这项工作。

function groupByPartAndType($input) {
  $output = Array();

  foreach($input as $value) {
    $output_element = &$output[$value['part'] . "_" . $value['type']];
    $output_element['part'] = $value['part'];
    $output_element['type'] = $value['type'];
    !isset($output_element['count']) && $output_element['count'] = 0;
    $output_element['count'] += $value['count'];
  }

  return array_values($output);
}

如果两个数据库都在同一个数据库服务器上,您将能够使用 SQLGROUP BY功能执行此操作。

于 2013-01-25T14:46:07.147 回答
1

以下:

$arr2 = array();
foreach ($arr1 as $a) {

  unset($a['address']);
  $key = $a['type'] . '-' . $a['part'];

  if (isset($arr2[$key])) {
    $arr2[$key]['count'] += $a['count'];
  } else {
    $arr2[$key] = $a;
  }

}
$arr2 = array_values($arr2);

会输出

array
  0 => 
    array
      'part' => string '1' (length=1)
      'type' => string '1' (length=1)
      'count' => int 15
  1 => 
    array
      'part' => string '2' (length=1)
      'type' => string '1' (length=1)
      'count' => int 10
  2 => 
    array
      'part' => string '2' (length=1)
      'type' => string '2' (length=1)
      'count' => int 5
于 2013-01-25T15:12:51.967 回答
0

就像是

 $newarr=array();
 foreach ( $arr as $Key => $Value ) {
 $newarr[$Value[part]][]=$arr[$key];
 }


 foreach ( $newarr[part] as $Key => $Value ) {
 ...
 }
于 2013-01-25T14:50:28.360 回答
0

多键数组分组的完整答案是

// *    $arr - associative multi keys data array
// *    $group_by_fields - array of fields to group by
// *    $sum_by_fields - array of fields to calculate sum in group

function array_group_by($arr, $group_by_fields = false, $sum_by_fields = false) {
    if ( empty($group_by_fields) ) return; // * nothing to group

    $fld_count = 'grp:count'; // * field for count of grouped records in each record group

    // * format sum by
    if (!empty($sum_by_fields) && !is_array($sum_by_fields)) {
        $sum_by_fields = array($sum_by_fields);
    }

    // * protected  from collecting
    $fields_collected = array();

    // * do
    $out = array();
    foreach($arr as $value) {
        $newval = array();
        $key = '';
        foreach ($group_by_fields as $field) {
            $key .= $value[$field].'_';
            $newval[$field] = $value[$field];
            unset($value[$field]);
        }
        // * format key
        $key = substr($key,0,-1);

        // * count
        if (isset($out[$key])) { // * record already exists
            $out[$key][$fld_count]++;
        } else {
            $out[$key] = $newval;
            $out[$key][$fld_count]=1;
        }
        $newval = $out[$key];

        // * sum by
        if (!empty($sum_by_fields)) {
            foreach ($sum_by_fields as $sum_field) {
                if (!isset($newval[$sum_field])) $newval[$sum_field] = 0;
                $newval[$sum_field] += $value[$sum_field];
                unset($value[$sum_field]);
            }
        }

        // * collect differencies
        if (!empty($value))
            foreach ($value as $field=>$v) if (!is_null($v)) {
                if (!is_array($v)) {
                    $newval[$field][$v] = $v;
                } else $newval[$field][join('_', $v)] = $v; // * array values 
            }

        $out[$key] = $newval;
    }
    return array_values($out);
}
于 2015-07-24T14:20:21.307 回答
0

如果在我的一个项目中这个任务是必要的,我会制作一个不需要引用变量或任何迭代函数调用的片段。

在循环内部,将复合临时键声明为变量(因为它被多次使用)。使用复合键作为临时一级键将新行推入结果数组。

使用 null 合并运算符以使用给定组的预先存在的计数,如果尚未遇到该组,则使用零。然后将新count值添加到先前累积的count.

每次重复时,此技术都会无条件地覆盖遇到的组。在此过程中,数据将在整个迭代过程中使用正确parttype、 和值进行更新。count

当循环结束时,通过调用重新索引结果数组array_values()

代码:(演示

$arr1 = [
    ['part' => '1', 'address' => 'aaa', 'type' => '1', 'count' => 5],
    ['part' => '1', 'address' => 'bbb', 'type' => '1', 'count' => 5],
    ['part' => '1', 'address' => 'ccc', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'aaa', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'bbb', 'type' => '1', 'count' => 5],
    ['part' => '2', 'address' => 'ccc', 'type' => '2', 'count' => 5]
];

$result = [];
foreach ($arr1 as $row) {
    $compositeKey = $row['part'] . '-' . $row['type'];
    $result[$compositeKey] = [
        'part' => $row['part'],
        'type' => $row['type'],
        'count' => ($result[$compositeKey]['count'] ?? 0) + $row['count']
    ];
}
var_export(array_values($result));

输出:

array (
  0 => 
  array (
    'part' => '1',
    'type' => '1',
    'count' => 15,
  ),
  1 => 
  array (
    'part' => '2',
    'type' => '1',
    'count' => 10,
  ),
  2 => 
  array (
    'part' => '2',
    'type' => '2',
    'count' => 5,
  ),
)

ps 理想情况下,此任务可能/应该在 sql 中执行,但我们没有提供任何具体指导的详细信息。

于 2020-12-05T14:24:30.923 回答