2012-05-08 4 views
8

У меня есть массив объектов. Я хотел бы удалить дубликаты на основе значения «name» в объекте.Удалить дубликаты из массива на основе свойства объекта?

[0]=> 
    object(stdClass)#337 (9) { 
    ["term_id"]=> 
    string(2) "23" 
    ["name"]=> 
    string(12) "Assasination" 
    ["slug"]=> 
    string(12) "assasination" 
    } 
    [1]=> 
    object(stdClass)#44 (9) { 
    ["term_id"]=> 
    string(2) "14" 
    ["name"]=> 
    string(16) "Campaign Finance" 
    ["slug"]=> 
    string(16) "campaign-finance" 
    } 
    [2]=> 
    object(stdClass)#298 (9) { 
    ["term_id"]=> 
    string(2) "15" 
    ["name"]=> 
    string(16) "Campaign Finance" 
    ["slug"]=> 
    string(49) "campaign-finance-good-government-political-reform" 
    } 

Таким образом, в этом случае, как удалить дубликат «кампании Финансы» объект из массива. Итак, весь объект [2]?

Здесь я столкнулся с проблемой дублирования массива PHP, но ни один из них не рассматривал объекты и фильтрацию сразу за одним параметром.

ответ

11

Создайте новый массив с существующими ключами и просто как имя, используйте array_unique (обратите внимание, что он сохраняет ключи).

Затем удалите все, что не в уникальном массиве, из оригинального ключа.

Edit: Полный пример:

class my_obj 
{ 
     public $term_id; 
     public $name; 
     public $slug; 

     public function __construct($i, $n, $s) 
     { 
       $this->term_id = $i; 
       $this->name = $n; 
       $this->slug = $s; 
     } 
} 

$objA = new my_obj(23, "Assasination", "assasination"); 
$objB = new my_obj(14, "Campaign Finance", "campaign-finance"); 
$objC = new my_obj(15, "Campaign Finance", "campaign-finance-good-government-political-reform"); 

$array = array($objA, $objB, $objC); 

echo "Original array:\n"; 
print_r($array); 

/** Answer Code begins here **/ 

// Build temporary array for array_unique 
$tmp = array(); 
foreach($array as $k => $v) 
    $tmp[$k] = $v->name; 

// Find duplicates in temporary array 
$tmp = array_unique($tmp); 

// Remove the duplicates from original array 
foreach($array as $k => $v) 
{ 
    if (!array_key_exists($k, $tmp)) 
     unset($array[$k]); 
} 

/** Answer Code ends here **/ 

echo "After removing duplicates\n"; 
print_r($array); 

Выход:

Original array: 
Array 
(
    [0] => my_obj Object 
     (
      [term_id] => 23 
      [name] => Assasination 
      [slug] => assasination 
     ) 

    [1] => my_obj Object 
     (
      [term_id] => 14 
      [name] => Campaign Finance 
      [slug] => campaign-finance 
     ) 

    [2] => my_obj Object 
     (
      [term_id] => 15 
      [name] => Campaign Finance 
      [slug] => campaign-finance-good-government-political-reform 
     ) 

) 
After removing duplicates 
Array 
(
    [0] => my_obj Object 
     (
      [term_id] => 23 
      [name] => Assasination 
      [slug] => assasination 
     ) 

    [1] => my_obj Object 
     (
      [term_id] => 14 
      [name] => Campaign Finance 
      [slug] => campaign-finance 
     ) 

) 

Объект с term_id 15 был удален, как это было такое же имя, как term_id 14.

+0

Это близко, но мне нужно получить доступ к «слизняк» и «term_id» ключа слишком. Я играю, чтобы посмотреть, смогу ли я это понять. –

+0

У вас есть доступ после этого, его просто для выяснения, какие ключи удалить. Я отправлю полный пример за секунду. – ccKep

+0

спасибо. отлично работает на довольно сложной проблеме, над которой я работал часами. – byron

1

Я искал хороший ответ на этот вопрос и не смог найти его, поэтому я написал свой собственный, который будет обрабатывать этот случай, и случай, когда вы хотите де-обмануть на основе нескольких свойств.

$array = DeDupeArrayOfObjectsByProps($array, ['name']); 

Вот общая функция:

/** 
* Iterates over the array of objects and looks for matching property values. 
* If a match is found the later object is removed from the array, which is returned 
* @param array $objects The objects to iterate over 
* @param array $props  Array of the properties to dedupe on. 
* If more than one property is specified then all properties must match for it to be deduped. 
* @return array 
*/ 
public function DeDupeArrayOfObjectsByProps($objects, $props) { 
    if (empty($objects) || empty($props)) 
     return $objects; 
    $results = array(); 
    foreach ($objects as $object) { 
     $matched = false; 
     foreach ($results as $result) { 
      $matchs = 0; 
      foreach ($props as $prop) { 
       if ($object->$prop == $result->$prop) 
        $matchs++; 
      } 
      if ($matchs == count($props)) { 
       $matched = true; 
       break; 
      } 

     } 
     if (!$matched) 
      $results[] = $object; 
    } 
    return $results; 
} 

Вот полное использование для Вашего случая:

class my_obj { 
    public $term_id; 
    public $name; 
    public $slug; 

    public function __construct($i, $n, $s) { 
     $this->term_id = $i; 
     $this->name = $n; 
     $this->slug = $s; 
    } 
} 

$objA = new my_obj(23, "Assasination", "assasination"); 
$objB = new my_obj(14, "Campaign Finance", "campaign-finance"); 
$objC = new my_obj(15, "Campaign Finance", "campaign-finance-good-government-political-reform"); 
$array = array($objA, $objB, $objC); 

$array = DeDupeArrayOfObjectsByProps($array, ['name']); 
var_dump($array); 
1

мне нужно было то же самое ... Вот что я сделал (работу как массива, так и объектов на основе this post)

function my_array_unique_by_subkey($array,$subkey){ 

    $temp = array(); 

    $unique = array_filter($array, function ($v) use (&$temp,$subkey) { 

     if (is_object($v)) $v = (array)$v; 

     if (!array_key_exists($subkey,$v)) return false; 

     if (in_array($v[$subkey], $temp)) { 
      return false; 
     } else { 
      array_push($temp, $v[$subkey]); 
      return true; 
     } 
    }); 

    return $unique; 
} 
0

Немного не по теме, но тесно связаны: кратчайший путь к DeDupe массив объектов только по их примеру:

/** 
* The array must NOT contain scalars. 
* 
* @param mixed[] $objects 
* @return mixed[] 
*/ 
public static function arrayUniqueForObjects(array $objects): array 
{ 
    $deDuplicatedArray = []; 

    foreach ($objects as $object) { 
     $deDuplicatedArray[spl_object_hash($object)] = $object; 
    } 

    return array_values($deDuplicatedArray); 
} 
+0

'spl_object_hash()' это хорошая идея !!! –

Смежные вопросы