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

问题描述 投票:0回答:4

我需要将行数组合并到组中,并使用每个组中的最低 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]]

php arrays multidimensional-array merge grouping
4个回答
4
投票

一种方法是按名字和姓氏分组,然后反转分组以获得单个 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 而不是一个。

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)
        ];
    }
}

2
投票
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
                )

        )

)

0
投票

@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);

0
投票

假设您的第一级键始终像示例数组中一样按升序排列(否则只需调用

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);
© www.soinside.com 2019 - 2024. All rights reserved.