[英]Group multidimensional array data based on two column values and sum values of one column in each group
我有一個數組,它是由來自兩個單獨數據庫的兩個數據庫查詢的組合創建的,它看起來類似於:
$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]
];
我正在尋找一種按part
和type
值對該數組進行分組的方法。 我還需要知道分組時count
數值的總數。
結果將類似於:
$arr2 = [
['part' => '1', 'type' => '1', 'count' => 15],
['part' => '2', 'type' => '1', 'count' => 10],
['part' => '2', 'type' => '2', 'count' => 5]
];
但我就是不知道該怎么做。 我見過幾個按單個鍵/值分組的例子,但沒有同時按多個值分組。
這個功能應該可以完成這項工作。
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);
}
如果兩個數據庫都在同一個數據庫服務器上,你可以使用 SQLs GROUP BY
功能來做到這一點。
以下:
$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
就像是
$newarr=array();
foreach ( $arr as $Key => $Value ) {
$newarr[$Value[part]][]=$arr[$key];
}
foreach ( $newarr[part] as $Key => $Value ) {
...
}
多鍵數組分組的完整答案是
// * $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);
}
如果這個任務在我的一個項目中是必要的,我會制作一個不需要引用變量或任何迭代函數調用的片段。
在循環內,將復合臨時鍵聲明為變量(因為它被多次使用)。 使用組合鍵作為臨時一級鍵將新行推入結果數組。
使用空合並運算符為給定組使用預先存在的計數,如果尚未遇到該組,則使用零。 然后將新的count
數值添加到先前累積的count
。
這種技術會在每次重復時無條件地覆蓋遇到的組。 這樣做時,數據將在整個迭代過程中使用正確的part
、 type
和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 中執行,但我們沒有提供任何具體指導的詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.