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 :)
We can also use a Set object to remove all duplicates from an array of objects. Copied! const arr = [ {id: 1, name: 'Tom'}, {id: 1, name: 'Tom'}, {id: 2, name: 'Nick'}, {id: 2, name: 'Nick'}, ]; const uniqueIds = new Set(); const unique = arr.
Arrays contains unique key. Hence if u are having multiple value for a single key, use a nested / multi-dimensional array. =) thats the best you got.
Answer: Use the indexOf() Method You can use the indexOf() method in conjugation with the push() remove the duplicate values from an array or get all unique values from an array in JavaScript.
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).
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.
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);
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);
You can also serialize first:
$unique = array_map( 'unserialize', array_unique( array_map( 'serialize', $array ) ) );
As of PHP 5.2.9 you can just use optional sort_flag SORT_REGULAR
:
$unique = array_unique( $array, SORT_REGULAR );
You can also use they array_filter function, if you want to filter objects based on a specific attribute:
//filter duplicate objects
$collection = array_filter($collection, function($obj)
{
static $idList = array();
if(in_array($obj->getId(),$idList)) {
return false;
}
$idList []= $obj->getId();
return true;
});
From here: http://php.net/manual/en/function.array-unique.php#75307
This one would work with objects and arrays also.
<?php
function my_array_unique($array, $keep_key_assoc = false)
{
$duplicate_keys = array();
$tmp = array();
foreach ($array as $key=>$val)
{
// convert objects to arrays, in_array() does not support objects
if (is_object($val))
$val = (array)$val;
if (!in_array($val, $tmp))
$tmp[] = $val;
else
$duplicate_keys[] = $key;
}
foreach ($duplicate_keys as $key)
unset($array[$key]);
return $keep_key_assoc ? $array : array_values($array);
}
?>
If you have an indexed array of objects, and you want to remove duplicates by comparing a specific property in each object, a function like the remove_duplicate_models()
one below can be used.
class Car {
private $model;
public function __construct( $model ) {
$this->model = $model;
}
public function get_model() {
return $this->model;
}
}
$cars = [
new Car('Mustang'),
new Car('F-150'),
new Car('Mustang'),
new Car('Taurus'),
];
function remove_duplicate_models( $cars ) {
$models = array_map( function( $car ) {
return $car->get_model();
}, $cars );
$unique_models = array_unique( $models );
return array_values( array_intersect_key( $cars, $unique_models ) );
}
print_r( remove_duplicate_models( $cars ) );
The result is:
Array
(
[0] => Car Object
(
[model:Car:private] => Mustang
)
[1] => Car Object
(
[model:Car:private] => F-150
)
[2] => Car Object
(
[model:Car:private] => Taurus
)
)
sane and fast way if you need to filter duplicated instances (i.e. "===" comparison) out of array and:
is:
//sample data
$o1 = new stdClass;
$o2 = new stdClass;
$arr = [$o1,$o1,$o2];
//algorithm
$unique = [];
foreach($arr as $o){
$unique[spl_object_hash($o)]=$o;
}
$unique = array_values($unique);//optional - use if you want integer keys on output
This is very simple solution:
$ids = array();
foreach ($relate->posts as $key => $value) {
if (!empty($ids[$value->ID])) { unset($relate->posts[$key]); }
else{ $ids[$value->ID] = 1; }
}
You can also make the array unique using a callback function (e.g. if you want to compare a property of the object or whatever method).
This is the generic function I use for this purpose:
/**
* Remove duplicate elements from an array by comparison callback.
*
* @param array $array : An array to eliminate duplicates by callback
* @param callable $callback : Callback accepting an array element returning the value to compare.
* @param bool $preserveKeys : Add true if the keys should be perserved (note that if duplicates eliminated the first key is used).
* @return array: An array unique by the given callback
*/
function unique(array $array, callable $callback, bool $preserveKeys = false): array
{
$unique = array_intersect_key($array, array_unique(array_map($callback, $array)));
return ($preserveKeys) ? $unique : array_values($unique);
}
Sample usage:
$myUniqueArray = unique($arrayToFilter,
static function (ExamQuestion $examQuestion) {
return $examQuestion->getId();
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With