简体   繁体   English

对数据行进行分组,在组内维护一个id的子数组,只呈现每组中最低的id作为第一级key

[英]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 作为第一级键,并确保第一级键不再存在于组的子数组中。

Code: ( Demo )代码:(演示

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.

相关问题 按列值对数据行进行分组,然后存储嵌套数据、第一次和最后一次出现以及每组内的计数 - Group rows of data by column value then store nested data, first and last occurrences, and counts within each group MySQL按concat值分组,并在每个组中获取第一个ID(UUID) - MySQL group by concat value and get first id (UUID) within each group 按级别分组行,并为每个行放置名称 - Group rows by level and put name for each 按二级键对二维数组数据进行分组并计算每组内的平均值 - Group 2d array data by second level keys and calculate average within each group 将来自两个二维 arrays 的数据按三列分组,并在每组内的另一列中保留最低值 - Group data from two 2d arrays by three columns and retaining the lowest value in another column within each group 将3d数组中的行数据按列分组,并合并每组中的子数组数据 - Group row data in a 3d array by a column and merge the subarray data in each group 按一列对子数组数据进行分组,并与每组中的辅助值形成逗号分隔的值 - Group subarray data by one column and form comma-separated values from the secondary value in each group 按一个列值对行数据进行分组,并用另一列值填充每个组中的子数组 - Group row data by one column value and populate a subarray in each group with the other column value SQL 计数和组仅返回每个组的第一行 - SQL count and group only returns first row for each group 如何在mysql中获取每个组的最低值 - How to get Lowest value of each group in mysql
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM