Remove duplicates from an array based on object property?

 ̄綄美尐妖づ 提交于 2019-11-27 03:26:05

问题


I have an array of objects. I'd like to remove the duplicates based on the "name" value in the object.

  [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"
  }

So in this case, how do I remove the duplicate "Campaign Finance" object from the array. So the entire [2] object?

I've gone through a bunch of the PHP duplicate array question here, but none seemed to deal with objects and filtering just off of one parameter.


回答1:


Build a new array with the existing keys and just the name as value, use array_unique (note that it preserves keys).

Then remove everything thats not in the unique'ed array from the original key-wise.

Edit: Complete example:

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

Output:

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
        )

)

The object with term_id 15 was removed as it had the same name as term_id 14.




回答2:


I was searching for a good answer to this and couldn't find one, so I've written my own that will handle this case, and the case when you want to de-dupe based on multiple properties.

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

Here's the generic function:

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

Here's the full usage for your case:

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



回答3:


I needed the same thing... Here's what I did (work for both array and objects, based on 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;
}



回答4:


Slightly off-topic, but closely related: the shortest way to dedupe an array of objects just by their instance:

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


来源:https://stackoverflow.com/questions/10505760/remove-duplicates-from-an-array-based-on-object-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!