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?
The array_unique() function removes duplicate values from an array. If two or more array values are the same, the first appearance will be kept and the other will be removed. Note: The returned array will keep the first array item's key type.
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:
Each array item is serialized. This will be unique based on the array's contents.
The results of this are run through array_unique
, so only arrays with unique signatures are left.
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.
Here's an improved version of @ryeguy's answer:
<?php $arr = array( array('user_id' => 33, 'tmp_id' => 3), array('user_id' => 33, 'tmp_id' => 4), array('user_id' => 33, 'tmp_id' => 5) ); # $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr))); $arr = array_intersect_key($arr, array_unique(array_map(function ($el) { return $el['user_id']; }, $arr))); //result: array 0 => array 'user_id' => int 33 'tmp_id' => int 3
First, it doesn't do unneeded serialization. Second, sometimes attributes may be different even so id is the same.
The trick here is that array_unique()
preserves the keys:
$ php -r 'var_dump(array_unique([1, 2, 2, 3]));' array(3) { [0]=> int(1) [1]=> int(2) [3]=> int(3) }
This let's array_intersect_key()
leave the desired elements.
I've run into it with Google Places API. I was combining results of several requests with different type of objects (think tags). But I got duplicates, since an object may be put into several categories (types). And the method with serialize
didn't work, since the attrs were different, namely, photo_reference
and reference
. Probably these are like temporary ids.
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