[英]Group rows of data, maintain a subarray of ids within the group, and only present the lowest id in each group as the first level key
I'm need to merge an array of rows into groups and use the lowest id in each group as the first level key.我需要将一组行合并到组中,并使用每个组中的最低 id 作为第一级键。 Within each group, all encountered ids (excluding the lowest) should be gathered in a subarray called
mergedWith
.在每个组中,所有遇到的 id(不包括最低的)都应收集在一个名为
mergedWith
的子数组中。
Sample input:样本输入:
[
1649 => ["firstName" => "jack", "lastName" => "straw"],
1650 => ["firstName" => "jack", "lastName" => "straw"],
1651 => ["firstName" => "jack", "lastName" => "straw"],
1652 => ["firstName" => "jack", "lastName" => "straw"],
]
My desired result:我想要的结果:
[
1649 => [
"firstName" => "jack"
"lastName" => "straw"
"mergedWith" => [1650, 1651, 1652]
]
]
I have a loop running that can pull out duplicates and find the lowest ID in the group, but not sure of the right way to collapse them into one.我有一个循环运行,可以提取重复项并找到组中最低的 ID,但不确定将它们合并为一个的正确方法。
I've shown the desired results of a search that has identified id's with duplicate entries in those particular fields.我已经显示了搜索的所需结果,该搜索已在这些特定字段中识别出具有重复条目的 id。 I just want to further refine it to not delete, but add a field on the end of each group that says
["mergedWith" => [1650, 1651, 1652]]
我只是想进一步完善它以不删除,而是在每个组的末尾添加一个字段,上面写着
["mergedWith" => [1650, 1651, 1652]]
One way to do it is to group by first name and last name, and then reverse the grouping to get a single id. 一种方法是按名字和姓氏分组,然后反转分组以获得单个ID。
krsort
the input beforehand to make sure you get the lowest 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];
}
}
Edit: not too much different based on your updated question. 编辑:根据您更新的问题,没有太多不同。 Just keep all the ids instead of a single one.
只保留所有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's answer is using a preliminary loop to create a lookup array, then nested loops to form the desired result. @Don'tPanic 的答案是使用初步循环来创建查找数组,然后使用嵌套循环来形成所需的结果。
I recommend a simpler approach without nested loops.我推荐一种没有嵌套循环的更简单的方法。 In the first loop, overpopulate the
mergedWith
element in each group -- this will be quite fast because there are no function calls and no conditions (aside from the null coalescing assignment operator, ??=
).在第一个循环中,过度填充每组中的
mergedWith
元素——这将非常快,因为没有 function 调用并且没有条件(除了 null 合并赋值运算符??=
)。 Then use a second loop to pull the first element from the mergedWith
subarray -- this will apply the lowest id as the first level key and ensure that the first level key no longer exists in the group's subarray.然后使用第二个循环从
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.