Making Objects in an Array Unique

Posted by Sean on Feb 06, 2009 under

I was doing some sorting of Models in PHP.  Unfortunately, I didn't have the luxury of letting the SQL do it all for me.  Usually it does.  But besides sorting, I had to make sure I didn't have any duplicate entries, since I was merging arrays with different queries.  My first hope was PHP's array_unique method.

array_unique($array) will return an array with all duplicate values removed.  What's deemed duplicate is when the string values are the same . This doesn't work for objects.  I had used usort previously, so I looked for something similar like a uunique or something.  No such luck.

I did find array_filter, which lets me specify a function the will determine what values get kept in the array and what gets ditched.  So I created a simple dummy function, inside make a static array, grab the id from each model value in the array.  I add the id to the static array, and then check the next value to see if the id has already been stored.

function unique_obj($obj) {
	static $idList = array();
	if(in_array($obj->id,$idList)) {
		return false;
	}
	$idList []= $obj->id;
	return true;
}
$posts = array_filter($posts,'unique_obj');

5 Comments

  1. Gravatar
    Marius Apr 10, 2009

    Just to make sure. You know about the "group by" part of SQL right? If you need unique combinations of fields, just use it in your query.

    SELECT name FROM users GROUP BY name,company
    
  2. Yes I know SQL could have handled this for me, but I mentioned I wasn't able to in this case. I was in a place where I couldn't write a custom query, just use 2 pre-existing queries, and then merge them in PHP.

  3. Your filter works fine as long as you want to filter just one array. For emulating the array_unique behavior, I would recommend analyzing the whole array.

    My solution...

    <?php
    	foreach($arr as $obj) {
    		if(!in_array((string) $obj,$list)) {
    			$list = (string) $obj;
    			$ret = $obj;
    		}
    	}
    	$arr = $obj;
    	return $arr;
    ?>
    

    But... Interesting piece of code. Is definitely much faster:)

  4. @vlki & @Sean

    The problem with using 'in_array' is that it is slow as sh*t !
    in_array checks the whole array each call.
    I prefer to use the id of each element as in:

    $arr = array.. .
    $unique = array();
    foreach( $arr as $k ) { if(!$unique[ $k['Id'] ]) { .. set it, do stuff.. } }
  5. @Tom Taylor: Good point about in_array. It does check most of the array, until it finds 1 occurrence of the needle.

    I was trying to get the performance benefits of array_filter, since that uses C code instead of interpreted PHP. I'm not sure which would perform better; a benchmark would determine what was indeed fastest, however, I doubt that would every be the bottleneck of an application.

Add a Comment

Search

Categories

Treats

  • No RSS feed found.
See all »