PHP在多个阵列中查找并显示重复值

时间:2015-09-08 01:18:09

标签: php arrays

所以我试图找到一种方法来搜索多个数组并让它过滤掉所有重复的条目,并让它显示找到重复条目的数组。

示例:

$array1 = array('domain.com','domain1.com','domain2.com','domain3.com','domain5.com','domaindd5.com');
$array2 = array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com');
$array3 = array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com');

然后读出会显示如下:

domain.com => array 1, array 2, array 3
domain5.com => array 1, array 3

提前感谢任何建议

6 个答案:

答案 0 :(得分:1)

这段代码背后的想法很简单:)对于所有提供的数组中的每个条目,该函数首先在$raw数组中记录容器数组的人工名称,然后删除没有更多的条目在该数组中出现一次。

<?php
function duplicates() {
    $raw = array();
    $args = func_get_args();
    $i = 1;
    foreach($args as $arg) {
        if(is_array($arg)) {
            foreach($arg as $value) {
                $raw[$value][] = "array $i";
            }
            $i++;
        }
    }

    $out = array();
    foreach($raw as $key => $value) {
        if(count($value)>1)
            $out[$key] = $value;
    }
    return $out;
}

echo '<pre>';
print_r(
    duplicates(
        array('domain.com','domain1.com','domain2.com','domain3.com','domain5.com','domaindd5.com'),
        array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com'),
        array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com')
    )
);
echo '</pre>';
?>

由于func_get_args()函数,您可以向上面的duplicates()函数提供任意数量的输入数组。以下是上述代码的输出:

Array
(
    [domain.com] => Array
        (
            [0] => array 1
            [1] => array 2
            [2] => array 3
        )

    [domain5.com] => Array
        (
            [0] => array 1
            [1] => array 2
            [2] => array 3
        )

    [domaindd5.com] => Array
        (
            [0] => array 1
            [1] => array 3
        )

)

答案 1 :(得分:0)

你的问题实际上让我真正感兴趣(有点太感​​兴趣)。解决方案需要通过排序数组进行迭代,并且数组包含的length无关紧要。您可能需要根据输入更改代码,但基本概念是相同的。您还可以通过添加一些foreach循环来更直观地为您进行配对(如下所述)。这就是我能想到的:

提案O(nlogn)复杂性算法

另一个解决方案和其他一些在线人员使用O(n^2)复杂性展示了一些方法。我认为我们可以做得更好,因为可以使用许多divide-and-conquer种类中完成的O(nlogn)过程来类似地解决这个问题。

快速总结

这是一个O(nlogn)运行时算法,它对数组进行排序,然后每次在较小的数组(具有较低current()元素的数组)中推进数组指针时运行它们,尝试查找任何数组重复。排序是O(logn)运行时,使用PHP的sort方法。

对数组进行排序

排序方法将使用sort,并将在稍后为数组的迭代存储变量$max_length。此过程为O(logn),其中n是要排序的数组输入的大小。这里我们将所有三个数组放在一个数组中并循环遍历它们以对它们进行排序。 (如果并非所有数组的长度都相同,则完成此操作)

<?php
$array1 = array('domain.com','domain1.com','domain2.com','domain3.com','domain5.com','domaindd5.com');
$array2 = array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com');
$array3 = array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com');
sort($array1);
sort($array2);
sort($array3);

迭代查找重复项

这部分有点不确定(我希望有些comp-sci专家可以帮我一点点,让它更快,因为我认为它可以更快)。我们正确地对数组进行了排序。我们需要做多少次迭代?答案是,这取决于!如果我们针对array1进行迭代以检查array2中的重复项,那么我们需要迭代直到达到最大元素(在array1array2中)。因为我们可以告诉array1具有最大的元素(你通过PHP中的max()来做这个,但是在这里你可以从字母中看出(所有元素都以domain开头,字母大于现在,我们要做的就是弄清楚我们需要达到的最大值是什么,以确保我们不会错过任何元素(例如,如果我们通过计算元素的数量来进行最大长度迭代在具有最大元素的数组中,我们会错过一些元素,因为在我们完成递增另一个较小的数组之前,循环可能会结束,因为该数组可能有许多小元素)。 现在,我们需要比较所有可能的paris(array1 - &gt; array2,array1 - &gt; array3,array2 - &gt; array3)并对它们进行迭代。每次迭代,我们将检查我们正在查看的当前元素是否大于另一个数组中的当前元素。如果是,我们将推进较小的数组指针,否则推进另一个数组。通过这样做,我们确保我们将访问每个元素,直到该元素相同(在这种情况下,我们到达else块,因为两个元素是相同的)。您可以阅读有关此策略的更多信息:Algorithm to tell if two arrays have identical members

对于每个while循环完成,我们重置两个数组中的数组指针,以便为下一次比较做好准备。

$end_of_array1 = end($array1);
reset($array1);
while (current($array1) != $end_of_array1) {
    if (current($array1) > current($array2)) {
        next($array2) || end($array2);
    }
    elseif (current($array1) < current($array2)) {
        next($array1) || end($array1);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array1)])) {
            array_push($duplicates[current($array1)], 'array1', 'array2');
        }
        else {
            $duplicates[current($array1)] =  array('array1', 'array2');
        }
        next($array1);
        next($array2);
    }
}
reset($array1);
$end_of_array3 = end($array3);
reset($array1);
reset($array2);
reset($array3);
while (current($array3) != $end_of_array3){
    if (current($array1) > current($array3)) {
        next($array3) || end($array3);
    }
    elseif (current($array1) < current($array3)) {
        next($array1) || end($array1);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array1)])) {
            array_push($duplicates[current($array1)], 'array1', 'array3');
        }
        else {
            $duplicates[current($array1)] = array('array1', 'array3');
        }
        next($array1);
        next($array3);
    }
}
reset($array2);
reset($array3);
while (current($array3) != $end_of_array3) {
    if (current($array2) > current($array3)) {
        next($array3) || end($array3);
    }
    elseif (current($array2) < current($array3)) {
        next($array2) || end($array2);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array2)])) {
            array_push($duplicates[current($array2)], 'array2', 'array3');
        }
        else {
            $duplicates[current($array2)] =  array('array2', 'array3');
        }
        next($array2);
        next($array3);
    }
}
foreach ($duplicates as $key=>$array) {
    $duplicates[$key] = array_unique($array);
}
print_r($duplicates);

$duplicates需要删除并变得独一无二,因为我们在其中推送了许多“array1”和“array3”。一旦完成,我们将达到所有重复的元素。

tl; dr和最后的笔记

完整代码位于下方,您可以运行here以确保获得相同的结果

<?php
$array1 = array('domain.com','domain1.com','domain2.com','domain3.com','domain5.com','domaindd5.com');
$array2 = array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com');
$array3 = array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com');
sort($array1);
sort($array2);
sort($array3);
$end_of_array1 = end($array1);
reset($array1);
while (current($array1) != $end_of_array1) {
    if (current($array1) > current($array2)) {
        next($array2) || end($array2);
    }
    elseif (current($array1) < current($array2)) {
        next($array1) || end($array1);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array1)])) {
            array_push($duplicates[current($array1)], 'array1', 'array2');
        }
        else {
            $duplicates[current($array1)] =  array('array1', 'array2');
        }
        next($array1);
        next($array2);
    }
}
reset($array1);
$end_of_array3 = end($array3);
reset($array1);
reset($array2);
reset($array3);
while (current($array3) != $end_of_array3){
    //echo 'current value of array1 :' . current($array1) . ' current value of array3: ' . current($array3). '<br/>';
    if (current($array1) > current($array3)) {
        next($array3) || end($array3);
    }
    elseif (current($array1) < current($array3)) {
        next($array1) || end($array1);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array1)])) {
            array_push($duplicates[current($array1)], 'array1', 'array3');
        }
        else {
            $duplicates[current($array1)] = array('array1', 'array3');
        }
        next($array1);
        next($array3);
    }
}
reset($array2);
reset($array3);
while (current($array3) != $end_of_array3) {
    if (current($array2) > current($array3)) {
        next($array3) || end($array3);
    }
    elseif (current($array2) < current($array3)) {
        next($array2) || end($array2);
    }
    else {
        //Array intersection, values are matching
        if (isset($duplicates[current($array2)])) {
            array_push($duplicates[current($array2)], 'array2', 'array3');
        }
        else {
            $duplicates[current($array2)] =  array('array2', 'array3');
        }
        next($array2);
        next($array3);
    }
}
foreach ($duplicates as $key=>$array) {
    $duplicates[$key] = array_unique($array);
}
print_r($duplicates);
?>

答案 2 :(得分:0)

从此处显示的$array1$array2$array3数组中,我假设同一数组中没有重复。

所以要完成两项任务

  • 在其他数组中查找重复项。
  • 创建一个包含重复发生名称的数组。

这是我的努力,

$final = []; // initialize the final array

foreach(array_merge($array1,$array2,$array3) as $domain)
    $final[] = $domain; // group all array's elements
unset($domain);         // unset garbage after foreach execution

现在,我们列出了所有阵列&#39;收集在$final中的元素。

$final = array_count_values($final); // find repetition and its count

$final = array_diff($final, [1]);    // remove single occurances

现在,final将如下所示,域名为关键字,并且在所有数组中重复次数。

array (
  'domain.com' => 3,
  'domain5.com' => 3,
  'domaindd5.com' => 2,
)

现在,找到给定3个数组中重复的位置

foreach($final as $domain => &$count)
{
    $count = []; // make count an array

    $temp1 = in_array($domain, $array1); // check if it is in $array1
    $temp2 = in_array($domain, $array2); // check if it is in $array2
    $temp3 = in_array($domain, $array3); // check if it is in $array3

    if($temp1 !== false) // if in array then fill array name
        $count[] = 'array1';
    if($temp2 !== false)
        $count[] = 'array2';
    if($temp3 !== false)
        $count[] = 'array3';
}
unset($domain, $count); // unset garbage

多数,你的$final数组看起来像,

array (
  'domain.com' => 
  array (
    0 => 'array1',
    1 => 'array2',
    2 => 'array3',
  ),
  'domain5.com' => 
  array (
    0 => 'array1',
    1 => 'array2',
    2 => 'array3',
  ),
  'domaindd5.com' => 
  array (
    0 => 'array1',
    1 => 'array3',
  ),
)

在行动中查看here

答案 3 :(得分:0)

如果你喜欢函数编程,这里有一个简洁的方法/一行:

代码:(Demo

$array1 = array('domain.com','domain1.com','domain2.com','domain3.com','domain5.com','domaindd5.com');
$array2 = array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com');
$array3 = array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com');

var_export(array_filter(array_merge_recursive(array_fill_keys($array1,'array1'),array_fill_keys($array2,'array2'),array_fill_keys($array3,'array3')),'is_array'));

输出:

array (
  'domain.com' => 
  array (
    0 => 'array1',
    1 => 'array2',
    2 => 'array3',
  ),
  'domain5.com' => 
  array (
    0 => 'array1',
    1 => 'array2',
    2 => 'array3',
  ),
  'domaindd5.com' => 
  array (
    0 => 'array1',
    1 => 'array3',
  ),
)

我没有资格与你谈论nlogn表现,但我认为它在简洁性方面非常有价值。

以下分为多行:

var_export(
    array_filter(
        array_merge_recursive(
            array_fill_keys($array1,'array1'), // ["domain.com"=>"array1","domain1.com"=>"array1",...]
            array_fill_keys($array2,'array2'),
            array_fill_keys($array3,'array3')
        ),
        'is_array'
    )
);
  • array_fill_keys()会生成一个数组,其中包含&#34; [...]。com&#34;值为键,&#34;数组变量名称&#34;作为静态值。
  • array_merge_recursive()将三个生成的数组合并为一个数组。重复键将其值合并到子数组中,而唯一键将其数据存储为字符串。
  • array_filter()只会移除唯一的&#34; [...]。com&#34;通过仅保留数据类型为array的值来发生。

答案 4 :(得分:0)

http://docs.php.net/array_intersect

返回一个数组,其中包含array1中所有值的值,其值存在于所有参数中。

    $array2 = array('domain.com','domain12.com','domain22.com','domain32.com','domain42.com','domain5.com');

    $array3 = array('domain.com','domain31.com','domain332.com','domain33.com','domain5.com','domaindd5.com');

    $duplicate = array_intersect(array_intersect($array1,$array2),$array3);

&GT?;

返回 的

的print_r($重复);

数组([0] =&gt; domain.com [4] =&gt; domain5.com)

答案 5 :(得分:0)

另一种方法,比其他答案更小/更简单,并允许详细输出。对于特定的用例,显然需要更多包装,但是希望您可以看到该方法。

$mar = [$array0, $array1, $array2];
foreach($mar as $i => $testAr){
    for ($ii=$i+1; $ii < count($mar); $ii++) { 
        foreach($mar[$ii] as $val){
            if (in_array($val, $testAr)){
                echo "$val in array $i and $ii<br>";
            }
        }
    }
}