Reputation: 2670
How can I compare objects inside of an array?
I have a dynamically populated array of simpleXML
objects (length is unknown)
Is there a fast way to compare all those objects inside the array and exclude duplicates?
And its getting a bit harder because ID field is different in every simpleXML object so I need to omit it in comparison.
For example simple short version:
Array
(
[0] => SimpleXMLElement Object
(
[ID] => 556
[FIRST] => JOHN
[MID] => SimpleXMLElement Object
(
)
[LAST] => SMITH
)
[1] => SimpleXMLElement Object
(
[ID] => 557
[FIRST] => JOHN
[MID] => SimpleXMLElement Object
(
)
[LAST] => SMITH
)
)
These are 2 duplicates. I need to confirm it and remove one.
This is what i have so far:
$noDups = array();
foreach($arr as $key=>$value)
{
if (0 == $key) {
$noDups[] = $value;
continue;
}
foreach($arr as $_key=>$_value)
{
$first = ( ((string)$value->FIRST) !== ((string)$_value->FIRST) )?true:false;
$mid = ( ((string)$value->MID) !== ((string)$_value->MID) )?true:false;
$last = ( ((string)$value->LAST) !== ((string)$_value->LAST) )?true:false;
if ($first && $mid && $last)
{
array_push($noDups, $value);
}
}
}
But i don't find this code sexy
if you know what i mean.
Upvotes: 1
Views: 893
Reputation: 235
The most efficient way to delete duplicates from an array is array_unique
function.
As stated in documentation, this function considers that two elements are equal if and only if their string representations are equal ( (string) $elem1 === (string) $elem2
).
The string represantion of objects can be handled by __toString
magic method.
SimpleXMLElement
already has __toString
implementation, so, in order to exclude ID from comparison, you need to override this method:
class ComparableXMLElement extends SimpleXMLElement
{
public function __toString()
{
//In order to exclude ID from comparison we need to return an unique string based only on specific attributes
return md5("F".$this->FIRST."_M".$this->MID."_L".$this->LAST);
}
}
Then you need populate your array with ComparableXMLElement
objects instead of SimpleXMLElement
and simple
$noDups = array_unique($arr);
will do the trick.
As a side note:
Since all comparison operators (e.g. !== ) already returns a boolean value, the use of ternary operator ( ? : ) is not necessary. So instead of
$first = ( ((string)$value->FIRST) !== ((string)$_value->FIRST) )?true:false;
you should write
$first = ((string)$value->FIRST) !== ((string)$_value->FIRST);
Upvotes: 1
Reputation: 12782
You can iterate over the array and build an associative array with key = what matters
$uniq = array();
foreach($arr as $obj) {
$uniq[$obj['FIRST'] . '::' . $obj['MID'] . '::' . $obj['LAST']] = $obj;
}
Upvotes: 0