array_diff是如何工作的?

2022-08-30 16:56:12

如何运作?它显然不能按如下方式工作:array_diff()

function array_diff($arraya, $arrayb)
{
    $diffs = array();
    foreach ($arraya as $keya => $valuea)
    {
        $equaltag = 0;
        foreach ($arrayb as $valueb)     
        {
            if ($valuea == $valueb)
            {
                $equaltag =1;
                break;
            }
        }
        if ($equaltag == o)
        {
              $diffs[$keya]=$valuea;
        }

    }
    return $diffs;                          
}                                  //couldn't be worse than this

有谁知道更好的解决方案?

编辑@animuson:

function array_diff($arraya, $arrayb)
{
    foreach ($arraya as $keya => $valuea)
    {
        if (in_array($valuea, $arrayb))
        {
            unset($arraya[$keya]);
        }
    }
    return $arraya;
}

答案 1

user187291的建议是通过哈希表在PHP中做到这一点,简直太棒了!在从这个幻想的想法中汲取的肾上腺素激增中,我甚至找到了一种方法来加速它(PHP 5.3.1):

function leo_array_diff($a, $b) {
    $map = array();
    foreach($a as $val) $map[$val] = 1;
    foreach($b as $val) unset($map[$val]);
    return array_keys($map);
}

使用从user187291的帖子中获取的基准测试:

LEO=0.0322  leo_array_diff()
ME =0.1308  my_array_diff()
YOU=4.5051  your_array_diff()
PHP=45.7114 array_diff()

即使在每个数组有 100 个条目时,array_diff() 性能滞后也很明显。

注意:此解决方案意味着第一个数组中的元素是唯一的(或者它们将变得唯一)。这是哈希解决方案的典型情况。

注意:该解决方案不会保留索引。将原始索引分配给$map最后使用 array_flip() 来保留键。

function array_diff_pk($a, $b) {
    $map = array_flip($a);
    foreach($b as $val) unset($map[$val]);
    return array_flip($map);
}

PS:我在寻找一些array_diff()悖论时发现了这一点:如果在脚本中使用两次,array_diff()几乎相同的任务需要三倍的时间。


答案 2

更新

  • 请参阅下面的更快/更好的代码。

  • array_diff行为在 php 5.3.4 中要好得多,但仍然比 Leo 的函数慢 10 倍。

  • 另外值得注意的是,这些函数并不严格等同,因为它们不维护数组键,即.array_diffmy_array_diff(x,y) == array_values(array_diff(x,y))

/更新

更好的解决方案是使用哈希映射

function my_array_diff($a, $b) {
    $map = $out = array();
    foreach($a as $val) $map[$val] = 1;
    foreach($b as $val) if(isset($map[$val])) $map[$val] = 0;
    foreach($map as $val => $ok) if($ok) $out[] = $val;
    return $out;
}

$a = array('A', 'B', 'C', 'D');
$b = array('X', 'C', 'A', 'Y');

print_r(my_array_diff($a, $b)); // B, D

基准

function your_array_diff($arraya, $arrayb)
{
    foreach ($arraya as $keya => $valuea)
    {
        if (in_array($valuea, $arrayb))
        {
            unset($arraya[$keya]);
        }
    }
    return $arraya;
}

$a = range(1, 10000);
$b = range(5000, 15000);

shuffle($a);
shuffle($b);

$ts = microtime(true);
my_array_diff($a, $b);
printf("ME =%.4f\n", microtime(true) - $ts);

$ts = microtime(true);
your_array_diff($a, $b);
printf("YOU=%.4f\n", microtime(true) - $ts);

结果

ME =0.0137
YOU=3.6282

有问题吗?;)

而且,只是为了好玩,

$ts = microtime(true);
array_diff($a, $b);
printf("PHP=%.4f\n", microtime(true) - $ts);

结果

ME =0.0140
YOU=3.6706
PHP=19.5980

太不可思议了!