考虑以下脚本。两个只有三个值的数组。当我使用array_intersect()比较这两个数组时。结果很快。
<?php
$arrayOne = array('3', '4', '5');
$arrayTwo = array('4', '5', '6');
$intersect = array_intersect($arrayOne, $arrayTwo);
print_r($intersect );
?>
我的问题是array_intersect()的效率是多少。是否我们比较两个都有1000个值的数组。会产生更好的结果.....我们需要使用一些哈希函数来处理快速找到常用值这将是有效的??? ..我需要你的建议......
我正在做一个应用程序。如果有人来登录并使用facebook登录。然后该应用程序将获取他的朋友列表并查找是否有任何朋友在我的应用程序之前评论并向他显示。大概一个朋友可能在Facebook有200到300个朋友,db有超过1000条记录。我需要有效地发现我该怎么做.......
答案 0 :(得分:20)
可以通过在第二个数组中构造一组搜索值来实现交集,并且可以使查找集合的速度非常快,以至于平均需要基本上恒定的时间。因此,整个算法的运行时间可以在O(n)
。
或者,可以对第二个数组进行排序(在O(n log n)
中)。由于查找已排序的数组在O(log n)
中具有运行时,因此整个算法应在O(n log n)
中具有运行时。
根据我刚刚运行的(简短的,不科学的)测试,这似乎是php array_intersect
的情况:
Here's the code我曾经测试过它。如您所见,对于小至1000的输入大小,您无需担心。
答案 1 :(得分:16)
array_intersect
在并行比较它们的值之前对数组进行排序(请参阅source file array.c中zend_qsort
的使用)。仅此一项就为每个数组提供O( n ·log n )。那么实际的交点只需要线性时间。
根据数组中的值,您可以在线性时间内实现此交集而不进行排序,例如:
$index = array_flip($arrayOne);
foreach ($arrayTwo as $value) {
if (isset($index[$value])) unset($index[$value]);
}
foreach ($index as $value => $key) {
unset($arrayOne[$key]);
}
var_dump($arrayOne);
答案 2 :(得分:2)
根据您的说法,我建议您实施缓存机制。这样你就可以加载数据库并加速你的应用程序。我还建议您使用越来越多的数据来分析array_intersect的速度,以了解性能如何扩展。您可以通过简单地将调用包装在系统时间的调用中并计算差异来完成此操作。但我建议你使用真实的分析器来获得好的数据。
答案 3 :(得分:2)
我找到的最快的解决方案:
function arrayIntersect($arrayOne, $arrayTwo) {
$index = array_flip($arrayOne);
$second = array_flip($arrayTwo);
$x = array_intersect_key($index, $second);
return array_flip($x);
}
我进行的测试如下:
function intersect($arrayOne, $arrayTwo)
{
$index = array_flip($arrayOne);
foreach ($arrayTwo as $value) {
if (isset($index[$value])) unset($index[$value]);
}
foreach ($index as $value => $key) {
unset($arrayOne[$key]);
}
return $arrayOne;
}
function intersect2($arrayOne, $arrayTwo)
{
$index = array_flip($arrayOne);
$second = array_flip($arrayTwo);
$x = array_intersect_key($index, $second);
return array_flip($x);
}
for($i =0; $i < 1000000; $i++) {
$one[] = rand(0,1000000);
$two[] = rand(0,100000);
$two[] = rand(0,10000);
}
$one = array_unique($one);
$two = array_unique($two);
$time_start = microtime(true);
$res = intersect($one, $two);
$time = microtime(true) - $time_start;
echo "Sort time $time seconds 'intersect' \n";
$time_start = microtime(true);
$res2 = array_intersect($one, $two);
$time = microtime(true) - $time_start;
echo "Sort time $time seconds 'array_intersect' \n";
$time_start = microtime(true);
$res3 = intersect2($one, $two);
$time = microtime(true) - $time_start;
echo "Sort time $time seconds 'intersect2' \n";
php 5.6的结果:
Sort time 0.77021193504333 seconds 'intersect'
Sort time 6.9765028953552 seconds 'array_intersect'
Sort time 0.4631941318512 seconds 'intersect2'
答案 4 :(得分:0)
我实现了比较array_intersect和array_intersect_key的简单代码,
$array = array();
for( $i=0; $i<130000; $i++)
$array[$i] = $i;
for( $i=200000; $i<230000; $i++)
$array[$i] = $i;
for( $i=300000; $i<340000; $i++)
$array[$i] = $i;
$array2 = array();
for( $i=100000; $i<110000; $i++)
$array2[$i] = $i;
for( $i=90000; $i<100000; $i++)
$array2[$i] = $i;
for( $i=110000; $i<290000; $i++)
$array2[$i] = $i;
echo 'Intersect to arrays -> array1[' . count($array) . '] : array2[' . count($array2) . '] ' . '<br>';
echo date('Y-m-d H:i:s') . '<br>';
$time = time();
$array_r2 = array_intersect_key($array,$array2);
echo 'Intercept key: ' . (time()-$time) . ' segs<br>';
$time = time();
$array_r = array_intersect($array,$array2);
echo 'Intercept: ' . (time()-$time) . ' segs<br>';
结果......
Intersect to arrays -> array1[200000] : array2[200000]
2014-10-30 08:52:52
Intercept key: 0 segs
Intercept: 4 segs
在比较array_intersect和array_intersect_key之间的效率时,我们可以看到使用键进行拦截的速度要快得多。