3

I have an array structured like this:

$arrNames = array(

array('first'=>'John', 'last'=>'Smith', 'id'=>'1'),
array('first'=>'John', 'last'=>'Smith', 'id'=>'2'),
array('first'=>'John', 'last'=>'Smith', 'id'=>'3')

)

I need to remove the similar elements where the fist and last name are the same. Normally, I would use array_unique but the elements aren't exactly unique since each one has a unique id. I do not care which id is retained. I just need the array to look like this:

$arrNames = array(

array('first'=>'John', 'last'=>'Smith', 'id'=>'1') // can be any id from the original array

)

Is there a quick way to accomplish this? My first thought is to use something like a bubble sort but I'm wondering if there is a better (faster) way. The resulting array is being added to a drop-down list box and the duplicate entries is confusing some users. I'm using the ID to pull the record back from the DB after it is selected. Therefore, it must be included in the array.

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
creatvepro
  • 169
  • 2
  • 11

2 Answers2

6
<?php

  $arrNames = array(
    array('first'=>'John', 'last'=>'Smith', id=>'1'),
    array('first'=>'John', 'last'=>'Smith', id=>'2'),
    array('first'=>'John', 'last'=>'Smith', id=>'3')
  );

  $arrFound = array();
  foreach ($arrNames as $intKey => $arrPerson) {
    $arrPersonNoId = array(
      'first' => $arrPerson['first'],
      'last' => $arrPerson['last']
    );
    if (in_array($arrPersonNoId, $arrFound)) {
      unset($arrNames[$intKey]);
    } else {
      $arrFound[] = $arrPersonNoId;
    }
  }
  unset($arrFound, $intKey, $arrPerson, $arrPersonNoId);

  print_r($arrNames);

This definitely works, whether it is the best way is up for debate...

Codepad

DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • 1
    Was writing something like this when you posted the answer. I would concat the first and last names to a string before inserting them into `$arrFound`. `in_array()` would be more efficient that way. – Tim Mar 19 '12 at 17:24
  • @Tim I initially wrote it like that, then I realised it is prone to error - what if you have two people, `John Sonsmith` and `Johnson Smith`? Obviously this could be overcome with casing, but may not be reliable if it comes from user input... – DaveRandom Mar 19 '12 at 17:27
  • Better solution would be to use `serialize()`. – Madara's Ghost Mar 19 '12 at 17:27
  • It is already in stackoverflow : http://stackoverflow.com/questions/1861682/php-multi-dimensional-array-remove-duplicate – Ben Mar 19 '12 at 17:27
  • @Truth That is a good idea as it could be easily made case insensitive – DaveRandom Mar 19 '12 at 17:27
  • @DaveRandom I thought of that: `$arrPerson['first'].'%%'.$arrPerson['last']`. Serialize is, imho, unnecessary overhead. String comparison could be made case-insensitive too. – Tim Mar 19 '12 at 17:31
1

There is no fast and easy way that I know of, but here is a relatively simple way of doing it assuming that the ids for "similar elements" don't matter (i.e. you just need an ID period).

$final = array();
foreach ($array as $values) {
   $final[$values['first'] . $values['last']] = $values;
}
$array = array_values($final);

The last step is not strictly necessary .. only if you want to remove the derived keys.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405