【问题标题】:PHP - How to compare two arrays and remove duplicate valuesPHP - 如何比较两个数组并删除重复值
【发布时间】:2012-01-31 06:09:46
【问题描述】:

所以这让我很困扰。

我有两个数组:

$array1 = array('[param1]' ,'demo' ,'[param2]' ,'some' ,'[param3]');
$array2 = array('value1'   ,'demo' ,'value2'   ,'some' ,'value3');

现在我想比较这两个数组,并删除所有重复值。
最后,我想要这两个数组,但其中没有“演示”和“某些”值。
我想从数组中删除所有具有相同索引键和值的值。
数组将始终具有相同数量的值和索引,我只想比较它们并从它们中删除具有相同索引键和值的条目。

我现在正在做这样的事情:

$clean1 = array();
$clean2 = array();    

foreach($array1 as $key => $value)
{
    if($value !== $array2[$key])
    {
        $clean1[$key] = $value;
        $clean2[$key] = $array2[$key];
    }
}

var_export($clean1);
echo "<br />";
var_export($clean2);

这行得通!但我想知道有没有其他方法可以做到这一点?也许不使用 foreach 循环?有没有更优雅的方式来做到这一点?

【问题讨论】:

  • 你能定义什么是“优雅”吗?我认为这里没有问题...
  • 这总是需要线性搜索。在这方面,您的解决方案是最有效的解决方案。
  • 这个问题不清楚,因为minimal reproducible example 的质量太差了。 I want to remove all values from array-s that have the same index key and value. 的逻辑语句在样本数据中没有得到很好的体现。这导致发布不适当尊重索引值关系的答案。

标签: php arrays


【解决方案1】:

没有比使用标准foreach() 循环更优雅的方式来处理您的两个数组。寻求功能等价物只会导致不必要的代码卷积。没有必要回避迭代结构——它不会让你看起来像一个“基本编码员”,它表明你知道解决问题的最简洁、最易读的方法。

而且太多其他答案不尊重指数-价值关系!

最终,您的问题的答案是:保持代码原样。

这是您如何使用函数式编程分别处理每个数组(array_diff_ukey() 不是必需的,array_merge() 的任何其他答案都会误解这个问题)。

代码:(Demo)

$arr_1 = ['[param1]', 'remove', 'demo', '[param2]', 'some', '[param3]'];
$arr_2 = ['value1',   'remove', 'some', 'value2',   'demo', 'value3'];

var_export(
    array_filter(
        $arr_1,
        function($value, $index) use ($arr_2) {
            return $arr_2[$index] !== $value;
        },
        ARRAY_FILTER_USE_BOTH
    )
);

echo "\n---\n";

var_export(
    array_filter(
        $arr_2,
        function($value, $index) use ($arr_1) {
            return $arr_1[$index] !== $value;
        },
        ARRAY_FILTER_USE_BOTH
    )
);

echo "\n---\n";

var_export(
    array_diff_assoc($arr_1, $arr_2)
);

echo "\n---\n";

var_export(
    array_diff_assoc($arr_2, $arr_1)
);

也就是说,如果您对基于构造的迭代有不自然的偏见,您可以使用这些单行代码,但它们会在后台对您的数据执行 4 次单独的迭代,而 foreach() 只执行一次。

代码:(Demo)

var_export(
    [
        'clean1' => array_values(array_diff_assoc($arr_1, $arr_2)),
        'clean2' => array_values(array_diff_assoc($arr_2, $arr_1))
    ]
);

【讨论】:

    【解决方案2】:

    例如我有两个数组,如下所示:

    $array1=Array([0] => parking.jpeg);
    $array2=Array ([0] => parking.jpeg [1] => logo.jpeg);
    

    首先从array1与array2进行比较,如下所示,将返回null

    $clean1 = array_diff($array1, $array2);
    

    从 array2 到 array1 的第二次比较将返回 logo.jpeg

    $clean2 = array_diff($array2, $array1);
    

    现在您可以将两个差异合并到一个数组中,如下所示:

    $final_output = array_merge($clean1, $clean2);
    

    输出:Array ( [0] =&gt; logo.jpeg )

    【讨论】:

      【解决方案3】:

      您的解决方案绝对是最“优雅”的(意味着最容易阅读,代码量最少),但这里有另一个使用array_diff_ukey() 的解决方案。它会保留密钥,并按照您的要求将它们按递增顺序排列。

      $array1 = ['[param1]' ,'demo' ,'[param2]' ,'some' ,'[param3]'];
      $array2 = ['value1'   ,'demo' ,'value2'   ,'some' ,'value3'];
      
      $clean1 = $array1;
      
      $clean2 = array_diff_ukey(
          $array2,
          $array1,
          // Need to have "&" so the values get set.
          function($a, $b) use (&$clean1, $array1, $array2) {
      
              // Use isset() just in case keys are not identical
              // or arrays are not the same length.
              if (isset($array2[$b]) && $array2[$b] === $array1[$b]) {
                  unset($clean1[$b]);
              }
      
              return strcmp($array2[$a], $array1[$b]);
      
      });
      
      print_r($clean1);
      print_r($clean2);
      

      会返回这个:

      Array
      (
          [0] => [param1]
          [2] => [param2]
          [4] => [param3]
      )
      Array
      (
          [0] => value1
          [2] => value2
          [4] => value3
      )
      

      工作示例here

      【讨论】:

        【解决方案4】:
        $clean1 = array_diff($array1, $array2); 
        $clean2 = array_diff($array2, $array1); 
        $final_output = array_merge($clean1, $clean2);
        

        【讨论】:

        • 请添加一些解释,以便人们了解为什么会这样
        • 此代码不会删除数组中的重复项
        【解决方案5】:

        怎么样?

        $res = array_diff($array1, $array_intersect($array1, $array2));
        $reindexed = array_combine(array_keys($res), array_values($res));
        

        如果不需要钥匙,也可以简单的方式

        array_values(array_diff($array1, $array_intersect($array1, $array2)));
        

        【讨论】:

          【解决方案6】:

          由于$array1$array2 的长度始终相同,您可以这样做:

          <?php
          
              $array1 = array('[param1]' ,'demo' ,'[param2]' ,'some' ,'[param3]');
              $array2 = array('value1'   ,'demo' ,'value2'   ,'some' ,'value3');
          
              $map = array_combine($array1,$array2);
              $map = array_filter($map ,function ($item) use (&$map) {
                  $keep_data = ($item != key($map));
                  next($map);
                  return $keep_data;
              });
          
              $clean1 = array_keys($map);
              $clean2 = array_values($map);
          
              var_export($clean1);
              echo "<br />";
              var_export($clean2);
          
          ?>
          

          更好吗?你决定

          【讨论】:

          • 哇,对我来说这个更复杂。我认为我在使用 foreach 循环时做得过分了,但看起来那是最好的方法。至少对我来说,对你来说,这个可能更清楚。感谢您的评论!
          • 是的...同意...而且速度也慢了 3 倍 :)
          【解决方案7】:

          您可以使用 PHP 中的函数 array_diff,它将返回包含两个数组之间相同键的数组。

          $clean1 = array_diff($array1, $array2);
          

          http://php.net/manual/en/function.array-diff.php

          【讨论】:

          • 谢谢!第二个是“优雅”!但是,它 array_diff 从 arr_1 中取消设置 $arr_2 中不存在的键。这对我来说可能是个问题:(我需要从 0 开始的新数组 :S 有没有办法重置数组键,如果我有像 0、3、7 这样的键,我可以将它们重置为 1,2, 3?
          • 这将删除第一个参数数组中的唯一元素。
          【解决方案8】:
          array_unique( array_merge($arr_1, $arr_2) );
          

          或者你可以这样做:

          $arr_1 = array_diff($arr_1, $arr_2);
          $arr_2 = array_diff($arr_2, $arr_1);
          

          我猜...

          【讨论】:

          • 谢谢!第二个是“优雅”!但是,array_diff 从 arr_1 中取消设置 $arr_2 中不存在的键,并返回带有不按顺序的键的数组。这对我来说可能是个问题:(我需要从 0 开始的新数组 :S 有没有办法重置数组键,如果我有像 0、3、7 这样的键,我可以将它们重置为 1,2, 3?如果不是,我就坚持第一个 foreach 循环。
          • 不错不错,不要遍历愚蠢的 PHP 的繁重循环 xD
          • 1. “最好不要遍历愚蠢的 PHP 的繁重循环”——这是无意义的,因为 php 的循环通常优于功能等效项。 2. OP 声明:“我想从数组-s 中删除所有具有相同索引键和值的值。" -- 重新排列输入数组中的元素以查看您的两个-ps 失败3v4l.org/oqgAa 这个答案不应该被接受或者问题不清楚。
          猜你喜欢
          • 2013-10-11
          • 2013-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-22
          • 1970-01-01
          • 2021-05-09
          • 2020-10-16
          相关资源
          最近更新 更多