我需要在一个多维数组中对数据进行分组,该数组可以在单列entry_id
上关联。
除了entry_id
之外,在其他相关行(ic
、name
和residency
)中也存在相同的其他列。分组时,可以简单地覆盖这些数据点——换句话说,我不需要在相应的组中收集相同值的多个副本。
最后,各个组中会有不同的数据点——这些值需要作为子数组存储在组中,这样就不会丢失数据。
如果一个组中只有一行的数据,则不需要将file_no
和detail
数据转换为数组。这意味着结果数组将具有可变的深度——一些行将是平面的,而另一些行可能是二维的。
样本输入:
$array = [
[
'entry_id' => 1,
'ic' => 2147483647,
'name' => 'Kořínková Blanka',
'residency' => 'Štětí, Lukešova 354, 411 08',
'file_no' => 'KSUL 77 INS 18898 / 2013',
'detail' => '749371da-725c-4738-8def-2f7167142a6f'
],
[
'entry_id' => 1,
'ic' => 2147483647,
'name' => 'Kořínková Blanka',
'residency' => 'Štětí, Lukešova 354, 411 08',
'file_no' => 'KSUL 77 INS 21218 / 2013',
'detail' => '43b6a718-4647-451d-9c53-50dfee8403ff'
],
[
'entry_id' => 2,
'ic' => 46900217,
'name' => 'ENTEC a.s. "v likvidaci"',
'residency' => 'Staré Město, Brněnská 1916, 686 03',
'file_no' => 'KSBR 28 INS 1232 / 2013',
'detail' => 'e2155a52-c464-4357-b71b-4f4ff75585eb'
],
];
所需输出(基于相同的"entry_id"分组):
Array
(
[0] => Array
(
[entry_id] => 1
[ic] => 2147483647
[name] => Kořínková Blanka
[residency] => Štětí, Lukešova 354, 411 08
[file_no] => Array
(
[0] => KSUL 77 INS 18898 / 2013
[1] => KSUL 77 INS 21218 / 2013
)
[detail] => Array
(
[0] => A749371da-725c-4738-8def-2f7167142a6f
[1] => 43b6a718-4647-451d-9c53-50dfee8403ff
)
)
[1] => Array
(
[entry_id] => 2
[ic] => 46900217
[name] => ENTEC a.s. "v likvidaci"
[residency] => Staré Město, Brněnská 1916, 686 03
[file_no] => KSBR 28 INS 1232 / 2013
[detail] => e2155a52-c464-4357-b71b-4f4ff75585eb
)
)
您的问题可以通过一个功能块来解决,使用array_reduce()
和array_merge()
原则:
$mergeId = 'entry_id';
$data = array_reduce($data, function($c, $x) use ($mergeId)
{
$c[$x[$mergeId]] = isset($c[$x[$mergeId]])
?array_combine(
$z=array_keys($c[$x[$mergeId]]),
array_map(function($y) use ($x, $c, $mergeId)
{
return in_array($x[$y], (array)$c[$x[$mergeId]][$y])
?$c[$x[$mergeId]][$y]
:array_merge((array)$c[$x[$mergeId]][$y], [$x[$y]]);
}, $z)
)
:$x;
return $c;
}, []);
如果需要重新索引结果集,则可能需要应用array_values()
(因此键将是连续的,从0
开始)。检查小提琴。
使用嵌套循环迭代单个数组以获得潜在匹配是一种间接的"暴力";技术——在一些边缘情况下,这是可以容忍的,但在这种情况下,更具性能和专业性的方法是在迭代每一行时分配临时的一级键。由于PHP处理数组/键的方式,新的关联数组允许简单/快速的搜索。
当第一次遇到entry_id
值时,只需保存整行即可。当第一次之后遇到entry_id
值时,需要将标量类型的file_no
和detail
元素转换为数组类型。这可以手动完成,但array_merge_recursive()
提供了这种"手动";魔术;天生的。
如果不想保留第一级分组密钥,请在迭代完成后调用array_values()
。
代码:(演示)
$result = [];
foreach ($array as $row) {
if (!isset($result[$row['entry_id']])) {
$result[$row['entry_id']] = $row;
} else {
$result[$row['entry_id']] = array_merge_recursive(
$result[$row['entry_id']],
['file_no' => $row['file_no'], 'detail' => $row['detail']]
);
}
}
var_export(array_values($result));
组内手动重新铸造元素(演示)
$result = [];
foreach ($array as $row) {
if (!isset($result[$row['entry_id']])) {
$result[$row['entry_id']] = $row;
} else {
$result[$row['entry_id']]['file_no'] = (array) $result[$row['entry_id']]['file_no']; // re-cast as single-element array
$result[$row['entry_id']]['detail'] = (array) $result[$row['entry_id']]['detail']; // re-cast as single-element array
$result[$row['entry_id']]['file_no'][] = $row['file_no']; // push new element into subarray
$result[$row['entry_id']]['detail'][] = $row['detail']; // push new element into subarray
}
}
var_export(array_values($result));