做以下操作会更快吗:
if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... }
或: if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... }
在某些值的情况下,使用其中一种方法会更快吗?
(在这种情况下,第二个选项中使用的数组尚不存在。)
做以下操作会更快吗:
if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... }
或: if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... }
在某些值的情况下,使用其中一种方法会更快吗?
(在这种情况下,第二个选项中使用的数组尚不存在。)
in_array()
,任何速度差异都可以忽略不计,但是单独测试每个变量的可读性很差。
仅供娱乐,这是我运行的一个测试:$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);
print "Time1: ". ($end - $start)."<br />";
$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);
print "Time2: ".($end2 - $start2)."<br />";
// Time1: 1.12536692619
// Time2: 1.57462596893
需要注意的是,如果$var
没有设置,则方法1需要更长时间(这取决于您测试了多少条件)。
Martijn:我已将数组扩展到五个元素,并查找test3
,作为一种平均情况。
PHP5.6
Time1: 0.20484399795532
Time2: 0.29854393005371
PHP7.1
Time1: 0.064045906066895
Time2: 0.056781053543091
PHP7.4
Time1: 0.048759937286377
Time2: 0.049691915512085
PHP8.0
Time1: 0.045055150985718
Time2: 0.049431085586548
结论:原始测试并不是最好的测试,而且在php7+中已经成为了一种偏好问题。
以下是与另一个案例相关的此工作台的实时更新 https://3v4l.org/OA2S7
PHP 7.3 的结果:
多次对比: 0.057507991790771
in_array: 0.02568507194519
循环外的 array_flip() + isset(): 0.014678001403809
循环外未经测量的 array_flip() + isset(): 0.015650033950806
foreach 和比较: 0.062782049179077
Time1: 1.33601498604
Time2: 4.9349629879
Time1: 1.34736609459
Time2: 6.29464697838
嗨,我刚刚举了一个极端的例子,指出随着值数量的增加,普通比较不是最高效的方式。
这是我的代码:
$var = 'test';
$num_values = 1000;
$iterations = 1000000;
print "\nComparison performance test with ".$num_values." values and ".$iterations." loop iterations";
print "\n";
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != 'test0' &&
$var != 'test1' &&
// ...
// yes I really have 1000 lines in my file
// ...
$var != 'test999') {}
}
print "\nCase 1: plain comparison";
print "\nTime 1: ". (microtime(true) - $start);
print "\n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array1[] = 'test'.$i;
}
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array1) ) {}
}
print "\nCase 2: in_array comparison";
print "\nTime 2: ".(microtime(true) - $start);
print "\n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array2['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
print "\nCase 3: values as keys, isset comparison";
print "\nTime 3: ".(microtime(true) - $start);
print "\n";
$start = microtime(true);
$array = array();
for($i=0; $i<$num_values; $i++) {
$array3['test'.$i] = 1;
}
for($i = 0; $i < $iterations; ++$i) {
if (!array_key_exists($var, $array3)) {}
}
print "\nCase 4: values as keys, array_key_exists comparison";
print "\nTime 4: ".(microtime(true) - $start);
print "\n";
我的结果(PHP 5.5.9):
Case 1: plain comparison
Time 1: 31.616894006729
Case 2: in_array comparison
Time 2: 23.226133823395
Case 3: values as keys, isset comparison
Time 3: 0.050863981246948
Case 4: values as keys, array_key_exists comparison
Time 4: 0.13700890541077
我同意,这可能有点极端,但它展示了PHP中类似哈希表的关联数组的大局和巨大潜力,你只需要好好利用它。
$array2 = array_flip($array);
$iterations = 10000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";
Time1: 12.875
Time2: 13.7037701607
Time3: 3.70514011383
switch ($var)
{ case 'test1': case 'test2': case 'test3': case 'test4':
echo "We have a good value"; break;
default:
echo "We do not have a good value";
}
$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
print "Time1: ". (microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array) ) {}
}
print "Time2: ".(microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, array('test1', 'test2', 'test3', 'test4')) ) {}
}
print "Time2a: ".(microtime(true) - $start);
$array2 = array_flip($array);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array2[$var])) {}
}
print "Time3: ".(microtime(true) - $start);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
$array2 = array_flip($array);
if (!isset($array2[$var])) {}
}
print "Time3a: ".(microtime(true) - $start);
我的结果:
Time1 : 0.59490108493 // straight comparison
Time2 : 0.83790588378 // array() outside loop - not accurate
Time2a: 2.16737604141 // array() inside loop
Time3 : 0.16908097267 // array_flip outside loop - not accurate
Time3a: 1.57209014893 // array_flip inside loop
array_flip
(与isset一起)比in_array更快,但不如直接比较快。我知道这个问题已经有将近10年的历史了,但是还有其他的方法可以做到这一点。我使用了Nick的页面上的B方法,并且处理了成千上万条记录。速度非常快。
foreach(array_values($haystack) as $v)
$new_haystack[$v] = 1;
}
// So haystack becomes:
$arr[“String1”] = 1;
$arr[“String2”] = 1;
$arr[“String3”] = 1;
// Then check for the key:
if (isset($haystack[$needle])) {
echo("needle ".$needle." found in haystack");
}
我的测试
$array = array('test1', 'test2', 'test3', 'test4');
$var = 'test';
$iterations = 1000000;
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') {}
}
$end = microtime(true);
print "Time1: ". ($end - $start)."<br />";
$start2 = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!in_array($var, $array) ) {}
}
$end2 = microtime(true);
print "Time2: ".($end2 - $start2)."<br />";
$array_flip = array_flip($array);
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array_flip[$var])) {}
}
$end = microtime(true);
print "Time3: ".($end - $start)."<br />";
$start = microtime(true);
for($i = 0; $i < $iterations; ++$i) {
if (!isset($array[$var])) {}
}
$end = microtime(true);
print "Time4: ". ($end - $start)."<br />";