array_unique for objects?

Is there any method like the array_unique for objects? I have a bunch of arrays with 'Role' objects that I merge, and then I want to take out the duplicates :)


Solution 1:

array_unique works with an array of objects using SORT_REGULAR:

class MyClass {
    public $prop;
}

$foo = new MyClass();
$foo->prop = 'test1';

$bar = $foo;

$bam = new MyClass();
$bam->prop = 'test2';

$test = array($foo, $bar, $bam);

print_r(array_unique($test, SORT_REGULAR));

Will print:

Array (
    [0] => MyClass Object
        (
            [prop] => test1
        )

    [2] => MyClass Object
        (
            [prop] => test2
        )
)

See it in action here: http://3v4l.org/VvonH#v529

Warning: it will use the "==" comparison, not the strict comparison ("===").

So if you want to remove duplicates inside an array of objects, beware that it will compare each object properties, not compare object identity (instance).

Solution 2:

Well, array_unique() compares the string value of the elements:

Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2 i.e. when the string representation is the same, the first element will be used.

So make sure to implement the __toString() method in your class and that it outputs the same value for equal roles, e.g.

class Role {
    private $name;

    //.....

    public function __toString() {
        return $this->name;
    }

}

This would consider two roles as equal if they have the same name.

Solution 3:

This answer uses in_array() since the nature of comparing objects in PHP 5 allows us to do so. Making use of this object comparison behaviour requires that the array only contain objects, but that appears to be the case here.

$merged = array_merge($arr, $arr2);
$final  = array();

foreach ($merged as $current) {
    if ( ! in_array($current, $final)) {
        $final[] = $current;
    }
}

var_dump($final);

Solution 4:

Here is a way to remove duplicated objects in an array:

<?php
// Here is the array that you want to clean of duplicate elements.
$array = getLotsOfObjects();

// Create a temporary array that will not contain any duplicate elements
$new = array();

// Loop through all elements. serialize() is a string that will contain all properties
// of the object and thus two objects with the same contents will have the same
// serialized string. When a new element is added to the $new array that has the same
// serialized value as the current one, then the old value will be overridden.
foreach($array as $value) {
    $new[serialize($value)] = $value;
}

// Now $array contains all objects just once with their serialized version as string.
// We don't care about the serialized version and just extract the values.
$array = array_values($new);