对数据行进行分组,维护组内的 id 子数组,并且仅将每个组中的最低 id 作为第一级键



我需要将一组行合并到组中,并使用每个组中的最低 id 作为第一级键。 在每个组中,所有遇到的 id(不包括最低的(都应收集在名为mergedWith的子数组中。

示例输入:

[
1649 => ["firstName" => "jack", "lastName" => "straw"],
1650 => ["firstName" => "jack", "lastName" => "straw"],
1651 => ["firstName" => "jack", "lastName" => "straw"],
1652 => ["firstName" => "jack", "lastName" => "straw"],
]

我想要的结果:

[
1649 => [
"firstName" => "jack"
"lastName" => "straw"
"mergedWith" => [1650, 1651, 1652]
]
]

我有一个循环正在运行,可以提取重复项并找到组中的最低 ID,但不确定将它们折叠为一个的正确方法。

我已经展示了搜索的所需结果,该搜索已识别出在这些特定字段中具有重复条目的 id。我只是想进一步细化它以不删除,而是在每个组的末尾添加一个字段,上面写着["mergedWith" => [1650, 1651, 1652]]

一种方法是按名字和姓氏分组,然后反转分组以获得单个 ID。 事先krsort输入以确保获得最低的 ID。

krsort($input);
//group
foreach ($input as $id => $person) {
// overwrite the id each time, but since the input is sorted by id in descending order,
// the last one will be the lowest id
$names[$person['lastName']][$person['firstName']] = $id;
}
// ungroup to get the result
foreach ($names as $lastName => $firstNames) {
foreach ($firstNames as $firstName => $id) {
$result[$id] = ['firstName' => $firstName, 'lastName' => $lastName];
}
}

编辑:根据您的更新问题没有太大差异。只需保留所有 ID 而不是单个 ID。

krsort($input);
foreach ($input as $id => $person) {
//                   append instead of overwrite ↓ 
$names[$person['lastName']][$person['firstName']][] = $id;
}
foreach ($names as $lastName => $firstNames) {
foreach ($firstNames as $firstName => $ids) {
// $ids is already in descending order based on the initial krsort
$id = array_pop($ids);  // removes the last (lowest) id and returns it
$result[$id] = [
'firstName' => $firstName,
'lastName' => $lastName,
'merged_with' => implode(',', $ids)
];
}
}
ksort($resArr);
$tempArr = array_unique($resArr, SORT_REGULAR);
foreach ($tempArr as $key => $value) {
foreach ($resArr as $key1 => $value2) {
if($value['firstName'] == $value2['firstName'] && $value['lastName'] == $value2['lastName']) {
$tempArr[$key]["mergedWith"][] = $key1;
}
}
}
print_r($tempArr);
$resArr = array(1650 => array(
"firstName" => "jack",
"lastName" => "straw"
),1649 => array(
"firstName" => "jack",
"lastName" => "straw"
)
,
1651 => array(
"firstName" => "jack",
"lastName" => "straw"
),
1652 => array(
"firstName" => "jack",
"lastName" => "straw"
),
1653 => array(
"firstName" => "jack1",
"lastName" => "straw"
),
1654 => array(
"firstName" => "jack1",
"lastName" => "straw"
));
Output
Array
(
[1649] => Array
(
[firstName] => jack
[lastName] => straw
[mergedWith] => Array
(
[0] => 1649
[1] => 1650
[2] => 1651
[3] => 1652
)
)
[1653] => Array
(
[firstName] => jack1
[lastName] => straw
[mergedWith] => Array
(
[0] => 1653
[1] => 1654
)
)
)

@Don'tPanic 的答案是使用初步循环来创建查找数组,然后嵌套循环以形成所需的结果。

我推荐一种没有嵌套循环的更简单的方法。 在第一个循环中,过度填充每个组中的mergedWith元素 - 这将非常快,因为没有函数调用和条件(除了空合并赋值运算符,??=(。 然后使用第二个循环从mergedWith子数组中提取第一个元素 - 这将应用最低 id 作为第一级键,并确保第一级键不再存在于组的子数组中。

代码:(演示(

ksort($array);
$temp = [];
foreach ($array as $key => $row) {
$compositeKey = $row['firstName'] . '-' . $row['firstName'];
$temp[$compositeKey] ??= $row;
$temp[$compositeKey]['mergedWith'][] = $key;
}
$result = [];
foreach ($temp as $row) {
$result[array_shift($row['mergedWith'])] = $row;
}
var_export($result);

假设您的第一级键始终像在示例数组中一样按升序排列(否则只需调用ksort()以应用基于第一级的升序排序(,请使用带有引用变量的单个循环。 如果再次遇到标识值,请将键推送到引用中,并从原始数组中删除当前行。

代码:(演示(

foreach ($array as $key => &$row) {
$compositeKey = $row['firstName'] . '-' . $row['firstName'];
if (!isset($ref[$compositeKey])) {
$ref[$compositeKey] = &$row;
} else {
$ref[$compositeKey]['mergedWith'][] = $key;
unset($array[$key]);
}
}
var_export($array);

最新更新