mariogl
mariogl

Reputation: 1295

Delete elements in an array with one value repeated

I have an array like this:

$elements = array(
    array("name" => "Paco", "group" => 2),
    array("name" => "Juan", "group" => 3),
    array("name" => "Marta", "group" => 2),
    array("name" => "Julia", "group" => 4),
    array("name" => "Silvia", "group" => 2)
);

I need to avoid repeating the group. If there are several elements with the same group, the final array must have only the first of each group:

$elements = array(
    array("name" => "Paco", "group" => 2),
    array("name" => "Juan", "group" => 3),
    array("name" => "Julia", "group" => 4)
);

Is there a better way than foreaching the array and processing each row? Something like GROUP BY in SQL?

Upvotes: 2

Views: 152

Answers (4)

Arnaud Le Blanc
Arnaud Le Blanc

Reputation: 99921

Alternative solution:

$groups = array_map(function($x) { return $x['group']; }, array_reverse($elements));
array_values(array_combine($groups, array_reverse($elements)));

Upvotes: 1

Crozin
Crozin

Reputation: 44376

You'll have to loop through entire array and manually remove duplicates:

$found = array();
foreach ($elements as $key => $element) {
    if (in_array($element['group'], $found, true)) {
        unset($elements[$key]);
    }

    $found[] = $element['group'];
}

In fact array_unique() function does the same, but on C level.

Upvotes: -1

Andreas
Andreas

Reputation: 2266

Seeing as a lot of strange code has come up, some are wildly inefficient or just strange in my opinion:

$values = array(); 

foreach($elements as $element) { 
    if (!isset($values[$element['group']])) {
        $values[$element['group']] = $element; 
    }
} 

And what you should have now is an array where only the FIRST occurence of a group is saved and only requires one pass, O(N). If you don't want the index to be the group id then just do:

$values2 = array_values($values);

PS. If you really dislike array_values(), then you could also do it like this (or some variation of this):

$values = array();
$groupkeys = array();

foreach($elements as $element) { 
    if (!isset($groupkeys[$element['group']])) {
         $values[] = $element;
         $groupkeys[$element['group']] = TRUE;
    } 
}

Upvotes: 4

profitphp
profitphp

Reputation: 8354

Try this, courtesy of the comments on php.net/array_unique, it makes a new array where the key is a hash of the serialized array, should prevent dupes in a multidimensional array.

<?php
$values = array();

foreach($elements as $element) {
    $values[md5(serialize($element))] = $element;
}

sort($values);
?> 

Upvotes: -1

Related Questions