基于对象属性继续从数组中删除重复项

时间:2016-12-02 22:16:06

标签: php arrays object

与:Remove duplicates from an array based on object property?

相关

有没有办法完成同样的事情,但考虑订单?例如,如果不是保持[2]我想保留[1]

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

我试过发表评论,但由于我的声誉,它不会让我所以我决定开始一个新的线程

3 个答案:

答案 0 :(得分:1)

这是一种方法。这应保留每个name属性的第一个对象,并删除其余属性。

$unique = [];

foreach ($array as $key => $object) {

    if (!isset($unique[$object->name])) {
        // this will add each name to the $unique array the first time it is encountered
        $unique[$object->name] = true;
    } else {
        // this will remove all subsequent objects with that name attribute
        unset($array[$key]);
    }
}

我使用对象名称作为键而不是$unique数组中的值,因此可以使用isset来检查现有名称,该名称应该比in_array更快。如果名称被添加为值,则必须使用。

答案 1 :(得分:1)

反转和数组是微不足道的。所以在处理数组之前,请在其上调用array_reverse()

/** flip it to keep the last one instead of the first one **/
$array = array_reverse($array);

如果订购是个问题,那么最后你可以再次反转它:

/** Answer Code ends here **/
/** flip it back now to get the original order **/
$array = array_reverse($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);

/** flip it to keep the last one instead of the first one **/
$array = array_reverse($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 **/
/** flip it back now to get the original order **/
$array = array_reverse($array);

echo "After removing duplicates\n";
echo "<pre>".print_r($array, 1);

产生以下输出

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

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

)

答案 2 :(得分:0)

您可以使用array_reduce

执行此操作
$names = [];

$withUniqueNames = array_reduce(
    [$objA, $objB, $objC],
    function ($withUniqueNames, $object) use (&$names) {
        if (!in_array($object->name, $names)) {
            $names[] = $object->name;
            $withUniqueNames[] = $object;
        } 

        return $withUniqueNames;
    },
    []
);

基本上,我们遍历一个对象数组并跟踪使用过的名称。如果名称尚未使用,我们将其添加到used并将当前对象添加到结果中。

这是working demo