Lambasoft
Lambasoft

Reputation: 999

Remove duplicates from a multidimensional array based on multiple keys

Sorry if this was asked before, but I searched a lot and couldn't find a solution. I've been trying to solve this problem for a while now, and couldn't write the function for it.

I have an array like that:

    $numbers = array(
        array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
        array("tag" => "student", "group" => "grp_1", "num" => "123123"),
        array("tag" => "student", "group" => "grp_2", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
    );

I need to write a function, that removes the duplicates off this array, based on multiple keys, so my function call should look something like that:

unique_by_keys($numbers, array("num","group"));

In other terms, one number can't be in the same group more than once.

After calling unique_by_keys() by array should be like that:

    $numbers = array(
        array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
        array("tag" => "student", "group" => "grp_2", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
    );

I'd appreciate if you could help me find a solution, or lead me to the correct way of thinking. Thanks!


SOLUTION: I was able to find a solution, by writing the following function: ( I wrote it in a way that accepts many forms of $haystack arrays )

function unique_by_keys($haystack = array(), $needles = array()) {
    if (!empty($haystack) && !empty($needles)) {
        $_result = array();
        $result = array();
        $i = 0;
        foreach ($haystack as $arrayObj) {
            if (is_array($arrayObj)) {
                $searchArray = array();
                foreach ($needles as $needle) {
                    if (isset($arrayObj[$needle])) {
                        $searchArray[$needle] = $arrayObj[$needle];
                    }
                }
                if (!in_array($searchArray, $_result)) {
                    foreach ($arrayObj as $key => $value) {
                        if (in_array($key, $needles)) {
                            $_result[$i][$key] = $value;
                        }
                    }
                    $result[] = array_merge($_result[$i], $arrayObj);
                }
            } else {
                $result[] = $arrayObj;
            }
            $i++;
        }
        return $result;
    }
}

Thanks for everyone that replied!

Upvotes: 1

Views: 721

Answers (3)

mickmackusa
mickmackusa

Reputation: 47874

Create composite string keys which represent the targeted/filtering column values -- this will assure sufficiently unique identification while filtering.

Using the "null coalescing assignment operator" (??=) will ensure that only the first encountered qualifying row will be retained.

Code: (Demo)

function unique_by_keys(array $haystack, array $needles): array {
    $columnNames = array_flip($needles);
    $result = [];
    foreach ($haystack as $row) {
        $compositeKey = implode('|', array_intersect_key($row, $columnNames));
        $result[$compositeKey] ??= $row;
    }
    return array_values($result);
}

var_export(
    unique_by_keys($numbers, ["group", "num"])
);

Upvotes: 3

Bhaskar Jain
Bhaskar Jain

Reputation: 1691

$newNumbers = array();
foreach($numbers as $key=>$values){
    $newkey = $values['group'].'__'.$values['num']; 
    $newNumbers[$newkey] = $values;
}
var_dump($newNumbers)

Upvotes: 1

Maha Dev
Maha Dev

Reputation: 3965

Code might not be efficient, but i will work for you :)

$result = unique_by_keys($numbers, array("num","group"));

echo "<pre>";
print_R($result);

function unique_by_keys($numbers, $arr){
    $new_array = array();
    $output = array();
    foreach ($numbers as $n){

        if(isset($new_array[$n[$arr[1]]]) && $new_array[$n[$arr[1]]] == $n[$arr[0]]){
            continue;
        }else{
            $new_array[$n[$arr[1]]] = $n[$arr[0]];
            $output[] = $n;
        }

    }
    return $output;
}

Upvotes: 0

Related Questions