Search code examples
phparraysmultidimensional-arrayfilteringkey-value

Remove key-value pairs found in subsequent rows while looping 2d array


I have a two dimensional array with indexed rows of associative elements. I need to retain the first occurring key-value pairs while iterating from the start of the array to the end.

Input:

$ar = [
     ["a" => "b", "c" => "d", "h" => "e"],
     ["a" = "b", "f" => "g"]
];

I've tried array_unique(), but it's not suitable for thistask.

Expected result:

[
     ["a" => "b", "c" => "d", "h" => "e"],
     ["f" => "g"]
]

Another example:

$ar = [
    ["a" => "b", "b" => "w", "c" => "e"!],
    ["c" => "g", "a" => "b"]
];

Expected result:

[
    ["a" => "b", "b" => "w", "c" => "e"],
    ["c" => "g"]
]

Solution

    • In this scenario, you need to be careful with duplicate keys yet different values. So match to remove duplicates has to be on combination of both key and value.

    • To do this, we can collect all keys in an array say $map and have all values visited for this keys inside that key array.

    • Now, we can just do an in_array check to get hold of whether we got some key-value pair like this before or not.

    Snippet:

    $arr = [
        [
            'a' => 'b',
            'c' => 'd',
            'h' => 'e'
        ],
        [
            'a' => 'b',
            'f' => 'g',
            'c' => 'f'
        ],
        [
            'a' => 'd',
            'c' => 'd'
        ]
    ];
    
    $map = [];
    foreach($arr as $index => $data){
        foreach($data as $key => $value){
            if(!isset($map[$key])) $map[$key] = [];
            if(in_array($value,$map[$key])) unset($arr[$index][$key]);
            else $map[$key][] = $value;
        }
    }
    
    print_r($arr);
    

    Demo: https://3v4l.org/RWcMu