Ama*_*mar 16 php arrays algorithm performance
我有2个非常大的阵列(大小约2,500,000).我需要找到这些数组之间的差异.差异我的意思是我需要一个结果数组,其值在数组1中但不在数组2中.我使用了array_diff()但它需要超过半小时!
第一个数组来自一个DB,第二个数组来自另一个数据库.它们不在同一个数据库服务器上.阵列的大小不同.我正在处理大量的手机号码.我需要找出一个列表中的移动号码,但不在另一个列表中
数组是带数字键的普通数组.Diff代码如下:
$numbers_list = array_diff($numbers_list, $some_other_list);
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法呢?请帮忙.
Shi*_*dim 28
这是一个简单的算法.
当您使用非常大的数组时,它会占用大量内存.
这是我的实施,
$a = file("l.a"); // l.a is a file contains 2,500,000 lines
$b = file("l.b");
function large_array_diff($b, $a){
// Flipping
$at = array_flip($a);
$bt = array_flip($b);
// checking
$d = array_diff_key($bt, $at);
return array_keys($d);
}
Run Code Online (Sandbox Code Playgroud)
我使用4G内存限制运行它.3G也有效.刚刚测试过
$ time php -d memory_limit=4G diff_la.php
Run Code Online (Sandbox Code Playgroud)
花了大约11秒钟!.
real 0m10.612s
user 0m8.940s
sys 0m1.460s
Run Code Online (Sandbox Code Playgroud)
UPDATE
以下代码运行速度比large_array_diff上述功能快2倍.
function flip_isset_diff($b, $a) {
$at = array_flip($a);
$d = array();
foreach ($b as $i)
if (!isset($at[$i]))
$d[] = $i;
return $d;
}
Run Code Online (Sandbox Code Playgroud)
因为它没有打电话array_flip(1次),array_diff_key而且array_keys.由此节省了大量CPU周期.
确定,更新,转换为字符串以获得良好的衡量标准(如果我们可以使用整数而不是字符串,则会产生很多不同......):
<?php
$start = microtime(true);
echo 'creating' . PHP_EOL;
$array1 = array();
$array2 = array();
for ($i = 0;$i < 2000000;$i++) {
$array1[] = (string)rand(100000000, 999999999);
$array2[] = (string)rand(100000000, 999999999);
}
echo (microtime(true) - $start) . PHP_EOL;
$start = microtime(true);
echo 'key diff flip' . PHP_EOL;
$array1f = array_flip($array1);
$array2f = array_flip($array2);
echo (microtime(true) - $start) . PHP_EOL;
$start = microtime(true);
echo 'key diff' . PHP_EOL;
$diff = array_diff_key($array1f, $array2f);
echo (microtime(true) - $start) . PHP_EOL;
$start = microtime(true);
echo 'sorting' . PHP_EOL;
$start = microtime(true);
sort($array1);
sort($array2);
$notin2 = array();
reset($array2);
echo (microtime(true) - $start) . PHP_EOL;
echo 'comparing' . PHP_EOL;
$start = microtime(true);
foreach ($array1 as $value) {
while (current($array2) < $value) {
if (next($array2) == false) break;
}
if (current($array2) != $value) $notin2[] = $value;
}
echo (microtime(true) - $start) . PHP_EOL;
echo 'plain diff' . PHP_EOL;
$start = microtime(true);
$diff = array_diff($array1, $array2);
echo (microtime(true) - $start) . PHP_EOL;
?>
Run Code Online (Sandbox Code Playgroud)
字符串
creating
8.66658186913
key diff flip
3.07359004021
key diff
1.48775887489
sorting
48.4047858715
comparing
9.41756916046
plain diff
19.21976614
real 1m37.574s
user 1m34.970s
sys 0m1.676s
Run Code Online (Sandbox Code Playgroud)
整数
(已删除(string)):
creating
4.69975805283
key diff flip
2.5843539238
key diff
1.4868490696
sorting
15.2628200054
comparing
5.62516498566
plain diff
101.688895941
real 2m18.090s
user 2m15.112s
sys 0m1.356s
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是...... array_diff似乎很讨厌整数......