如何在PHP中删除重复的二维数组?

时间:2009-08-08 04:12:04

标签: php arrays

我从以前的帖子中得到一些想法,就是为每个$ 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);

有人可以为此发布功能吗?

非常感谢!

5 个答案:

答案 0 :(得分:17)

快速而简单:

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

答案 1 :(得分:0)

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; 

} 

答案 2 :(得分:0)

这是另一个想法。再一次,不是非常优雅,但可能非常快。它类似于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);
}

答案 3 :(得分:-1)

哈希是一个好主意,它会使解决方案平均为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数组,因此在输入的基数非常大之前,您将看不到性能优势!

答案 4 :(得分:-1)

这取决于你是否有资源将较大的数组保留在内存中(所以基本上,它取决于你是否只需要唯一的值来防止它在循环中膨胀,或者你只需​​要最终的结果是一系列独特的价值观。

对于所有示例,我假设您从一些外部源获取值进入大数组,如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);