4
\$\begingroup\$

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 ?

\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

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;
}
\$\endgroup\$
5
  • \$\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\$ 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\$ 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\$ Aug 17, 2013 at 6:08
  • \$\begingroup\$ Yes, but what if the array is random? \$\endgroup\$ 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\$ Aug 17, 2013 at 8:45
1
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ If I get him right he wants to use the last not the first duplicate each. \$\endgroup\$ Aug 16, 2013 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.