I'm trying to achieve a set of unique array with my following function.
The Function:
/**
* uniqueAssocArray Removes arrys which have same keys
* @param Array $array Array to get unique items from
* @param String $uniqueKey the unique key
* @return Array new array with unique items
* @author Junaid Qadir Baloch <[email protected]>
*/
function uniqueAssocArray($array, $uniqueKey) {
if (!is_array($array)) {
return array();
}
$uniqueKeys = array();
foreach ($array as $key => $item) {
if (!in_array($item[$uniqueKey], $uniqueKeys)) {
$uniqueKeys[$item[$uniqueKey]] = $item;
}
}
return $uniqueKeys;
}
Example Array:
$actualArray = array(
user1 => array(
'name' => 'User1',
'age' => '25',
'lastLogin' => '2013-08-16'
),
user1 => array(
'name' => 'User1',
'age' => '25',
'lastLogin' => '2013-08-10'
),
user2 => array(
'name' => 'User2',
'age' => '35',
'lastLogin' => '2013-08-08'
),
user1 => array(
'name' => 'User1',
'age' => '25',
'lastLogin' => '2013-07-10'
)
);
I then call the function like so:
$resultArray = uniqueAssocArray($actualArray, 'name');
But...
I wonder is there a better way to do the same ?
2 Answers 2
Assuming your array is already sorted, you can just overwrite the values every time. Skip the inner if.
function uniqueAssocArray($array, $uniqueKey) {
if (!is_array($array)) {
return array();
}
$uniqueKeys = array();
foreach ($array as $key => $item) {
$groupBy=$item[$uniqueKey];
if (isset( $uniqueKeys[$groupBy]))
{
//compare $item with $uniqueKeys[$groupBy] and decide if you
//want to use the new item
$replace= ...
}
else
{
$replace=true;
}
if ($replace) $uniqueKeys[$groupBy] = $item;
}
return $uniqueKeys;
}
-
\$\begingroup\$ Haha! i had already done the same but I have to accept your answer. There's one catch though, Array must be sorted in reverse order. and I test for existence for a key before I replace the values blindly. \$\endgroup\$Junaid Qadir Shekhanzai– Junaid Qadir Shekhanzai2013年08月16日 16:55:44 +00:00Commented Aug 16, 2013 at 16:55
-
\$\begingroup\$ @mnhgI hope you won't mind if i un-accept your answer. I'm still looking for a better way \$\endgroup\$Junaid Qadir Shekhanzai– Junaid Qadir Shekhanzai2013年08月17日 03:54:51 +00:00Commented Aug 17, 2013 at 3:54
-
\$\begingroup\$ If you want the last element each, you need an ascending order. You are just overwriting the value again and again until you are on the last key. \$\endgroup\$mheinzerling– mheinzerling2013年08月17日 06:08:57 +00:00Commented Aug 17, 2013 at 6:08
-
\$\begingroup\$ Yes, but what if the array is random? \$\endgroup\$Junaid Qadir Shekhanzai– Junaid Qadir Shekhanzai2013年08月17日 08:36:38 +00:00Commented Aug 17, 2013 at 8:36
-
\$\begingroup\$ If performance doesn't matter, sort it. If you want to handle this in the same loop just compare the current items key value with the already inserted. \$\endgroup\$mheinzerling– mheinzerling2013年08月17日 08:45:59 +00:00Commented Aug 17, 2013 at 8:45
Maybe you should try to use the function array_unique
: http://php.net/manual/en/function.array-unique.php
If you prefer to go with your own solution, have a look at the method array_key_exists
(http://www.php.net/manual/en/function.array-key-exists.php) to replace your condition:
if (!array_key_exists($key, $uniqueKeys)) {
$uniqueKeys[$item[$uniqueKey]] = $item;
}
A bit off-topic here, but you probably don't want to store a user's age but rather her birthday, to make sure it stays up-to-date.
-
\$\begingroup\$ If I get him right he wants to use the last not the first duplicate each. \$\endgroup\$mheinzerling– mheinzerling2013年08月16日 12:36:50 +00:00Commented Aug 16, 2013 at 12:36