문제

다음을 수행하는 것이 더 빠릅니다.

 if ($var != 'test1' && $var != 'test2' && $var != 'test3' && $var != 'test4') { ... }

또는:

 if (!in_array($var, array('test1', 'test2', 'test3', 'test4') { ... }

한 시점에 여러 가지 값이 있습니까?

(이 경우 두 번째 옵션에 사용 된 배열은 AlReay가 존재하지 않습니다.)

도움이 되었습니까?

해결책

나는 단지 사용하는 것만 강하게 제안하는 것을 제안한다 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은 훨씬 더 오래 걸립니다 (테스트 된 조건에 따라 다름)

다른 팁

당신이 많은 것을 교체하려는 경우 !== 진술, 세 번째 매개 변수를 전달해야합니다 in_array ~처럼 true, 배열의 항목에 대한 유형 확인을 시행합니다.

평범한 != 분명히 이것을 요구하지 않습니다.

첫 번째는 더 빠릅니다. 두 번째는 오버 헤드가 많습니다. 배열 생성, 함수 호출, 배열 검색 ...

그러나 내가 질문에서 말했듯이 몇 가지 답변이 적기 때문에 조기 최적화는 모든 악의 근본입니다. 읽을 수 있도록 코드를 작성해야합니다. 만약에 프로파일을 최적화 한 다음 최적화해야합니다.

편집하다:

@Owen의 코드 (Php 5.2.6 / Windows)와의 타이밍 :

Time1: 1.33601498604
Time2: 4.9349629879

질문에서와 같이 배열 (...)을 루프 내부로 이동합니다.

Time1: 1.34736609459
Time2: 6.29464697838

in_array는 많은 품목의 경우 더 빠릅니다. "대형"은 데이터 및 컴퓨터와 관련된 많은 요인을 기반으로 매우 주관적입니다. 당신이 묻고 있기 때문에, 나는 당신이 사소한 수의 품목을 다루지 않는다고 가정합니다. 더 긴 목록의 경우,주의하십시오 이 정보, PHP가 선형 검색 대신 해시 조회를 활용할 수 있도록 뒤집힌 배열로 성능을 측정하십시오. 조정하는 "정적"배열의 경우 성능이 향상되지는 않지만 또한 수도 있습니다.

더 일관된 결과를 얻기 위해 배열 된 배열과 더 많은 반복이있는 Owen의 테스트 코드 사용 :

$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

안녕하세요 저는이 사건을 극단으로 가져 가서 평범한 값이 증가함에 따라 평범한 비교가 ~ 아니다 가장 성능있는 방법.

내 코드는 다음과 같습니다.

$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의 해시 테이블과 같은 연관 배열의 큰 그림과 큰 잠재력을 보여줍니다.

Roborg가 지적했듯이 배열을 생성하는 데 오버 헤드가 있으므로 반복 루프 내부로 이동해야합니다. 이러한 이유로 Sparr의 게시물은 Array_flip 함수와 오버 헤드가 있기 때문에 약간 오해의 소지가 있습니다.

다음은 5 가지 변형이 모두있는 또 다른 예입니다.

$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과 함께)는 inarray보다 빠르지 만 직선 비교만큼 빠르지는 않습니다.

PHP에 대해 말하면

  • "if"s and "else ifs"세트,
  • "IF"세트가있는 "IF"또는 "ED 조건 (원래 게시물 세부 사항에서와 같이) 또는
  • 비행 비행 배열과 함께 "in_array"사용,

더 나은,

PHP 언어 "스위치"문은 그러한 상황을 위해 설계된 대안이며 더 나은 답변 일 수 있음을 명심해야합니다. (포스터의 예는 우리가 두 가지 솔루션을 비교하게 만들지 만 실제 질문 제목은 in_array 대 PHP 문을 고려해야하므로 이것이 공정한 게임이라고 생각합니다).

포스터의 예에서는 대신 추천합니다.

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";
}

PHP가 "또는"에 대한 쉼표와 같은 경우에는 몇 가지 비-프리맨티 구성을 허용하기를 바랍니다. 그러나 위의 내용은 PHP의 디자이너가 이것을 처리하는 가장 분명한 방법으로 간주 한 것입니다. 그리고 다른 두 가지 대안보다 실행 시간에 더 효율적인 것으로 보입니다.

내가 위시리스트에 대해 이야기하는 한, SQL에서 발견 된 "In"은 포스터의 예제 상황에서 훨씬 더 명확합니다.

이 사고는 아마도 그러한 상황에서 "in_array"를 사용하고 싶어하는 사람들에게 이어지는 것일 것입니다. 그러나 데이터 구조를 구축 한 다음 해당 데이터 구조를 위해 설계된 술어를 사용해야하는 것은 불행한 일입니다. 오버 헤드가 일어나지 않고 말하십시오.

다음은 다른 케이스와 함께이 벤치의 라이브 업데이트입니다. https://3v4l.org/oa2s7

PHP 7.3의 결과 :

  • 다중 비교 : 0.057507991790771

  • in_array : 0.02568507194519

  • Array_flip () 외부 루프 측정 + isset () : 0.014678001403809

  • Array_flip () 외부 루프 측정 + isset () : 0.015650033950806

  • 외식 및 비교 : 0.062782049179077

나는이 질문이 거의 10 년이되었지만 다른 방법이 있습니다. 나는 방법 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 />";

시간 1 : 0.20001101493835

Time2 : 0.32601881027222

Time3 : 0.072004079818726

Time4 : 0.070003986358643

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top