【问题标题】:How to remove duplicated 2-dimension array in PHP?如何在 PHP 中删除重复的二维数组?
【发布时间】:2009-08-08 04:12:04
【问题描述】:

我从以前的帖子中得到了一些想法,这些帖子正在讨论为每个 $array[$i] 制作一个哈希值,然后比较哈希以获得唯一的数组,但我不知道我能具体做什么.

我的样本数组数据:

$arr[] = array(0,1,2,3);
$arr[] = array(4,5,2,1);
$arr[] = array(0,0,0,0);
$arr[] = array(0,1,2,3);

我预计会回来:

$arr[] = array(0,1,2,3);
$arr[] = array(4,5,2,1);
$arr[] = array(0,0,0,0);

任何人都可以为此目的向我发布一个功能吗?

非常感谢!

【问题讨论】:

    标签: php arrays


    【解决方案1】:

    快速简单:

    $arr = array_map('unserialize', array_unique(array_map('serialize', $arr)));
    

    【讨论】:

    • 这种方法是不完美的,如果条目的顺序不同,它不会捕获重复,serialize(['a' => ['b' => 1], 'c' => ['d' => 2]]),serialize(['c' => ['d' => 2], 'a' => ['b' => 1]])
    • @GajusKuizinas:无论如何,PHP 数组定义并不相同:codepad.org/nsTS5bDc。但是,如果这就是您想要的,只需事先使用适当的排序功能。
    • 顺便问一下,你为什么要使用(un)serialize?除非我弄错了,json_encode/json_decode 应该会快很多。
    • @GajusKuizinas:当我写这篇文章时,速度要慢得多(我认为现在更快了)。无论如何,还有其他原因,因为 JSON 不能理解所有 PHP 类型。
    • 如果序列化和反序列化的速度低于遍历数组的速度,这就是天才,因为速度很重要。
    【解决方案2】:
    foreach($arr as $key => $value)
    {
       foreach($arr as $key2 => $value2)
       {
          if($value2 == $value && $key != $key2)
           {
              unset($arr[$key]);
           }
        }
    }
    

    这不是最优雅的方法,但它完全可以满足您的需要。问题是你不能递归地使用array_unique。

    这是PHP.net documentation comments 的另一种方式(里面有很棒的代码片段)

    function arrayUnique($myArray) 
    { 
        if(!is_array($myArray)) 
               return $myArray; 
    
        foreach ($myArray as &$myvalue){ 
            $myvalue=serialize($myvalue); 
        } 
    
        $myArray=array_unique($myArray); 
    
        foreach ($myArray as &$myvalue){ 
            $myvalue=unserialize($myvalue); 
        } 
    
        return $myArray; 
    
    } 
    

    【讨论】:

      【解决方案3】:

      这是另一个想法。同样,不是非常优雅,但可能很快。类似于 Chacha102 的第二部分,不过如果子数组中只有整数值会更快。

      // implode the sub arrays
      $tmpArray = array();
      foreach ($arr as $key => $array) {
          $tmpArray[$key] = implode(',', $array);
      }
      
      // get only the unique values
      $tmpArray = array_unique($tmpArray);
      
      // explode the values
      $arr = array();
      foreach ($tmpArray as $key => $string) {
          $arr[$key] = explode(',', $string);
      }
      

      【讨论】:

        【解决方案4】:

        散列是个好主意,它会使解决方案平均为 O(n)

        基本上,您遍历 $arr 并对整个数组进行哈希处理,然后将其与之前看到的哈希值进行比较(这是使用 isset() 的 O(1),或者准确地说是 O(m)其中 m 是内部数组中的元素数)。如果发生冲突,则比较实际的数组元素。通常,冲突意味着您之前已经看过该数组并且它是重复的,但这不能保证。这是一些实现此算法的伪 php。

        function mkhash($array = array()) {
           $hash = "";
           foreach ($array as $element) {
              $hash .= md5($element);
           }
        }
        
        $seen = array();
        $newArray = array();
        foreach($arr as $elementArray) {
           $hash = mkhash($elementArray); 
           if(!isset($seen[$hash])) {
             $newArray[] = $elementArray;
             $seen[$hash] = $elementArray;
           } else if(count(array_diff($elementArray, $seen[$hash])) > 0) {
              $newArray[] = $elementArray; //this is true if two different arrays hashed to the same element
           }
        }
        

        哈希方法更难实现,正确处理冲突也很棘手,所以有 O(nlogn)。

        这样做的 O(nlogn) 方法是对数组进行排序

        $arr = array_multisort($arr); //O(nlogn)
        

        然后你要做的就是比较相邻的数组,看看它们是否重复

        当然,您可以简单地使用 O(n^2) 方法并将每个内部数组与每个其他内部数组进行比较...

        编辑:哦,这是另一个 O(n) 的想法,您可以使用映射到其他数组的数组键递归地构建一个 trie,因此您最终会得到一个 m 级深数组,其中 m 是您拥有的最长的内部数组. trie 的每个分支代表一个唯一的内部数组。当然,您必须编写一些开销代码才能将 trie 转换回 2D 数组,因此在输入的基数非常大之前,您不会看到性能优势!

        【讨论】:

          【解决方案5】:

          这取决于您是否有资源将较大的数组保存在内存中(所以基本上,这取决于您是否只需要唯一值以防止它在循环期间膨胀,或者您是否只需要最终结果一组唯一值。

          对于所有示例,我假设您从某个外部源(如 MySQL 查询)获取要输入大数组的值。

          为了防止重复输入到主数组中:

          您可以创建两个数组,一个将值作为字符串,一个将值作为实际数组值。

          while($row = $results->fetch_assoc) {
               $value_string = implode("," $row);
               if(in_array($value_string, $check_array) {
                   $check_array[] = $value_string;
                   $master_array[] = $row;
                }
           }
          

          在上面,它只是查看你的数据集的字符串版本是否在已经迭代过的字符串数据集的数组中。使用两个数组最终会产生更大的开销,但它们都不会得到重复的值。

          或者,正如已经提到的,我敢肯定,有array_unique,它发生在输入所有数据之后。修改上面的例子,得到

          while($row = $results->fetch_assoc) {
               $master_array[] = $row;
             }
           $master_array = array_unique($master_array);
          

          【讨论】:

          • 没有 cmets 的投票是非常粗鲁的。谢谢大家。
          猜你喜欢
          • 2017-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-05-07
          • 2015-05-22
          相关资源
          最近更新 更多