up vote 3 down vote favorite
share [g+] share [fb]

HAy, i have an array

Array(
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[1] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[2] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 8
        [frame_id] => 8
    )

[3] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

[4] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

As you can see key 0 is the same as 1,3 and 4. And key 2 is different from them all.

When running the array_unique function on them, the only left is

Array (
[0] => Array
    (
        [0] => 33
        [user_id] => 33
        [1] => 3
        [frame_id] => 3
    )

)

any ideas why array_unique isn't working as expected?

link|improve this question

feedback

3 Answers

up vote 13 down vote accepted

It's because array_unique compares items using a string comparison. From the docs:

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

The string representation of an array is simply the word Array, no matter what its contents are.

You can do what you want to do by using the following:

$arr = array(
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 3),
    array('user_id' => 33, 'frame_id' => 8)
);

$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));

//result:
array
  0 => 
    array
      'user_id' => int 33
      'user' => int 3
  2 => 
    array
      'user_id' => int 33
      'user' => int 8

Here's how it works:

  1. Each array item is serialized. This will be unique based on the array's contents.

  2. The results of this are run through array_unique, so only arrays with unique signatures are left.

  3. array_intersect_key will take the keys of the unique items from the map/unique function (since the source array's keys are preserved) and pull them out of your original source array.

link|improve this answer
Wish I could +1 this twice. Beautiful. – Steve Sep 19 '11 at 8:20
feedback

array_unique() only supports multi-dimensional arrays in PHP 5.2.9 and higher.

Instead, you can create a hash of the array and check it for unique-ness.

$hashes = array(); 

foreach($array as $val) { 
    $hashes[md5(serialize($d))] = $val; 
} 

array_unique($hashes);
link|improve this answer
the serialized string should be enough for comparing the strings. when using md5 with long serialized strings, you risk collision. Also, I'd use array_map with un/serialize before and after unique. – Gordon Apr 1 '10 at 15:02
@Gordon collisions are so improbable that it isn't even worth worrying about. – ryeguy Apr 1 '10 at 15:06
1  
@ryeguy that depends on your application. and also doesn't change that it's unnecessary in the first place. – Gordon Apr 1 '10 at 15:07
feedback

array_unique deosn't work recursive, so it just thinks "this are all Arrays, let's kill all but one... here we go!"

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

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