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