Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 阵列_diff是如何工作的?_Php_Performance_Arrays - Fatal编程技术网

Php 阵列_diff是如何工作的?

Php 阵列_diff是如何工作的?,php,performance,arrays,Php,Performance,Arrays,array\u diff()是如何工作的?它显然无法按如下方式工作: function array_diff($arraya, $arrayb) { $diffs = array(); foreach ($arraya as $keya => $valuea) { $equaltag = 0; foreach ($arrayb as $valueb) { if ($valuea ==

array\u 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;
}

了解其工作原理的最佳解决方案是查看其源代码;-)
(好吧,这是开源的威力之一——如果你看到一些可能的优化,你可以提交一个补丁;-))

对于array_diff,它应该位于
ext/standard
——这意味着,对于PHP5.3,它应该位于:

然后,该文件看起来像一个可信的目标;
php\u array\u diff
函数第3381行似乎对应于
array\u diff


(祝您好运:代码很长……

来自PHP:“返回一个数组,其中包含来自array1的所有条目,而这些条目在任何其他数组中都不存在。”

因此,只需对照所有arrayN检查array1,array1中未出现在这些数组中的任何值都将在新数组中返回

您甚至不必遍历所有array1的值。对于所有附加数组,循环遍历它们的值,并检查每个值是否在数组($array1,$value)中更新

  • 以获得更快/更好的代码

  • 在PHP5.3.4中,array_diff的性能要好得多,但仍然比Leo的函数慢约10倍

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

/更新

更好的解决办法是使用

基准

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
ME =0.0140
YOU=3.6706
PHP=19.5980
有问题吗?;)

而且,只是为了好玩

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

ME =0.0137
YOU=3.6282
ME =0.0140
YOU=3.6706
PHP=19.5980

太不可思议了

user187291建议通过哈希表在PHP中实现这一点,这简直太棒了!从这个幻觉的想法中汲取了大量的肾上腺素,我甚至找到了一种方法来加速它(PHP5.3.1):

根据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个条目,数组_diff()的性能滞后也很明显

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

注意:解决方案不保留索引。将原始索引分配给$map,最后使用数组_flip()保留键

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

PS:我是在寻找一些数组的时候发现这个的。paradoxon:array_diff()如果在脚本中使用两次,几乎相同的任务所花费的时间是原来的三倍。

既然已经提到了这个问题(见@BurninLeo的答案),那么类似这样的事情呢

function binary_array_diff($a, $b) {
    $result = $a;
    asort($a);
    asort($b);
    list($bKey, $bVal) = each($b);
    foreach ( $a as $aKey => $aVal ) {
        while ( $aVal > $bVal ) {
            list($bKey, $bVal) = each($b);
        }
        if ( $aVal === $bVal ) {
            unset($result[$aKey]);
        }
    }
    return $result;
}
进行一些测试后,结果似乎是可以接受的:

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

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

$ts = microtime(true);
for ( $n = 0; $n < 10; ++$n ) {
    array_diff($a, $b);
}
printf("PHP    => %.4f\n", microtime(true) - $ts);

$ts = microtime(true);
for ( $n = 0; $n < 10; ++$n ) {
    binary_array_diff($a, $b);
}
printf("binary => %.4f\n", microtime(true) - $ts);

$binaryResult = binary_array_diff($a, $b);
$phpResult    = array_diff($a, $b);
if ( $binaryResult == $phpResult && array_keys($binaryResult) == array_keys($phpResult) ) {
    echo "returned arrays are the same\n";
}

当然,PHP代码的性能不如C代码,因此PHP代码的速度稍慢也就不足为奇了。

似乎可以通过使用另一个数组而不是不稳定的数组来大大提高速度。不过,这会占用更多内存,这可能是一个取决于用例的问题(我还没有测试内存分配的实际差异)


这三个新功能是在

-1中发现的,它比这更复杂。目前正在使用先进的算法和数据结构。看帕斯卡的答案。这仍然是一个基本的想法正在发生什么,是一个比他更好的解决方案。是的,在这种情况下,我认为我不应该停止使用C。。。但是,在同样的拥有中,没有遗憾^^^^哦!!真是难以置信+1.我感到惊讶的是,这甚至更快,尽管与array_diff不同,索引关联丢失了:array_键(array_diff_键(array_fill_键($a,1),array_fill_键($b,1)))另外,如果$a包含重复的值,而不是$b中的值,这些值将丢失。PHP现在速度快得多了ME=0.0036 YOU=0.1217 PHP=0.0018与PHP 7.4相同ME=0.0066 YOU=0.1145 PHP=0.0014虽然这是一个相当老的主题,但我今天才找到它,但我无法复制您所说的内容,以便将关联数组作为输出。添加了另一个短函数
array_diff_pk
保留键,也保留在关联数组中。然而,我没有测试
array\u flip
的性能或整体功能。还请注意,只有在处理大型阵列时,使用这些替换函数才有意义,因为大型阵列实际上会导致内置函数(同时经过优化)的性能。我非常喜欢您的解决方案。我刚刚尝试了这些替换函数,而内置函数的实际数据行数约为200k,而且内置速度快得多(几秒钟)这些版本甚至在我感到无聊并取消流程之前都没有完成。(~5分钟?)
PHP    => 1.3018
binary => 1.3601
returned arrays are the same
<?php
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;
}
function leo_array_diff($a, $b) {
  $map = $out = array();
  foreach($a as $val) $map[$val] = 1;
  foreach($b as $val) unset($map[$val]);
  return array_keys($map);
}
function flip_array_diff_key($b, $a) {
  $at = array_flip($a);
  $bt = array_flip($b);
  $d = array_diff_key($bt, $at);
  return array_keys($d);
}
function flip_isset_diff($b, $a) {
  $at = array_flip($a);
  $d = array();
  foreach ($b as $i)
    if (!isset($at[$i]))
      $d[] = $i;
  return $d;
}
function large_array_diff($b, $a) {
  $at = array();
  foreach ($a as $i)
    $at[$i] = 1;
  $d = array();
  foreach ($b as $i)
    if (!isset($at[$i]))
      $d[] = $i;
  return $d;
}

$functions = array("flip_array_diff_key", "flip_isset_diff", "large_array_diff", "leo_array_diff", "my_array_diff", "array_diff");
#$functions = array_reverse($functions);
$l = range(1, 1000000);
$l2 = range(1, 1000000, 2);

foreach ($functions as $function) {
  $ts = microtime(true);
  for ($i = 0; $i < 10; $i++) {
    $f = $function($l, $l2);
  }
  $te = microtime(true);
  $timing[$function] = $te - $ts;
}
asort($timing);
print_r($timing);
[flip_isset_diff] => 3.7415699958801
[flip_array_diff_key] => 4.2989008426666
[large_array_diff] => 4.7882599830627
[flip_flip_isset_diff] => 5.0816700458527
[leo_array_diff] => 11.086831092834
[my_array_diff] => 14.563184976578
[array_diff] => 99.379411935806