【问题标题】:remove duplicates from an array based on object property continued根据对象属性从数组中删除重复项(续)
【发布时间】:2016-12-02 22:16:05
【问题描述】:

相关: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"
  }

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

【问题讨论】:

    标签: php arrays object


    【解决方案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】:

      这是一种方法。这应该保留每个 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 更快,如果名称被添加为值。

      【讨论】:

      • @sevavietl 我改变了原始数组,因为这似乎是这个问题所基于的链接问题的目标。 $unique 将只持有来自$array 的每个name 属性作为键,并且在循环之后,任何具有重复名称的对象都将被删除。
      • 啊,不用担心。
      【解决方案3】:

      您可以使用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。

      【讨论】:

        猜你喜欢
        • 2012-05-17
        • 2020-06-29
        • 2016-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-14
        • 2014-03-08
        • 1970-01-01
        相关资源
        最近更新 更多