Удалить дубликаты из массива на основе свойства объекта?

У меня есть массив объектов. Я хотел бы удалить дубликаты на основе значения «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, но ни один из них не имел дело с объектами и фильтрацией сразу за одним параметром.

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

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

Изменить: полный пример:

 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); с 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.

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

 $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); 

Мне нужно то же самое … Вот что я сделал (работайте как с массивом, так и с объектами, на основе этого сообщения )

 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; } 

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

 /** * 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); }