phprecursionmultidimensional-arrayduplicatesarray-unique

Recursively remove duplicate values from lowest subarrays of a multidimensional (3+levels) array


I've done various research and no testing method worked with 3 levels or more arrays.

I need to leave only the only ones values in the multidimensional array.

See this example

My Array:

$array = [
    'sucesso' => [
        'LAUDO_VISTORIA' => [
            0 => '0027',
            2 => '30027',
            3 => '0027',
        ],
        'LAUDO' => [
            0 => '0027',
            2 => '30027',
            3 => '0027',
        ],
        'DADOS_DO_VEICULO' => [
            0 => '0027',
            1 => '30027',
        ]
    ],
    'code' => 201
];

Solution

  • Please note that if you have numbers with leading zero, you should store them to as strings, otherwise they will be interpreted as octal numbers. You can use (int) to get the correct type cast, when you output them.

    The first code below flatten the array by the use of serialize as callback in array_map, duplicates are removed using array_unique, then put back together using array_intersect_key, the process is looped to get to deeper levels of the array.

    The second code below, follows the same logic but array_unique is only performed at the deepest level of each array key path. An if/else statement has been added, as not all array key path are of the same length/depth. (If anyone knows of a better way to do so, please let me know.)

    serialize can be replaced with json_encode, but I am not sure which is faster.

    I am not very good at explaining how things work, please feel free to edit, if you can rephrase what I've said above better.

    To remove duplicates in multidimensional arrays, both duplicated sub-arrays and elements.

        function multi_unique($array){
            $temp = array_intersect_key($array, array_unique(array_map("serialize", $array)));
            foreach ($temp as $key => $value){
                if ( is_array($value) ){
                    $temp[$key] = multi_unique($value);
                }
            }
            return $temp;
        }
    

    To remove duplicate elements from the sub-array of the deepest end of each key path.

        function multi_unique($array){
            $temp = array_intersect_key($array, array_map("serialize", $array));
            foreach ($temp as $key => $value){
                if (is_array($value)){
                   $temp[$key] = multi_unique($value);
                }
    //the else if statement is to counter the problem where the deepest level of each path is different
                else if (count($temp) == count($temp, COUNT_RECURSIVE)){
                    $temp=array_unique($temp);
                }
            }
            return $temp;
        }