Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use array_unique on an array of arrays?

Tags:

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?

like image 909
dotty Avatar asked Apr 01 '10 14:04

dotty


People also ask

What is use of Array_unique in PHP?

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.


2 Answers

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.

like image 85
ryeguy Avatar answered Oct 15 '22 00:10

ryeguy


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.

like image 22
x-yuri Avatar answered Oct 15 '22 00:10

x-yuri