2016-05-13 6 views
0

私はコンピュータ科学者ではなく、アルゴリズム上の知識が豊富ですが、今日はPHPのin_arrayメソッドがどのようにしてうまく動作するのか疑問に思っていました。それはかなり単純明快で、すべての配列の要素をループし、与えられた値に対して現在の要素をチェックします。しかし、より大きなアレイであっても、それは非常に迅速に動作します。どうやって?PHPのin_array関数はどのように機能しますか?

<?php 
$distros = ["Mint", "Debian", "Ubuntu", "Fedora", "CentOS", "Arch"]; 
if (in_array("Ubuntu", $distros)) { 
    echo "Got Ubuntu"; 
} 
+0

は "非常に迅速に" を定義します。 –

+5

特別な魔法はありません。一致するものが見つかるまで(または配列の最後に到達するまで)、比較を行う各エントリをループします。つまり、次のことを意味します。それはO(n)であり、配列内の「さらに下方に」は一致が見つかると時間がかかります。または配列が長ければ長いほど、それは長くかかるでしょう –

+2

このようなものは、big-O表記が表す「最悪の場合」を強調します。平均ケースはn/2で、最良のケースは1です。もし 'in_array'の速度をテストしたいのであれば、あなたが探しているものは、最悪の場合の測定を得るために配列に現れてはいけません。 –

答えて

2

ここにある:

/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) 
* 0 = return boolean 
* 1 = return key 
*/ 
static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ 
{ 
    zval *value,    /* value to check for */ 
     *array,    /* array to check in */ 
     *entry;    /* pointer to array entry */ 
    zend_ulong num_idx; 
    zend_string *str_idx; 
    zend_bool strict = 0;  /* strict comparison or not */ 

#ifndef FAST_ZPP 
    if (zend_parse_parameters(ZEND_NUM_ARGS(), "za|b", &value, &array, &strict) == FAILURE) { 
     return; 
    } 
#else 
    ZEND_PARSE_PARAMETERS_START(2, 3) 
     Z_PARAM_ZVAL(value) 
     Z_PARAM_ARRAY(array) 
     Z_PARAM_OPTIONAL 
     Z_PARAM_BOOL(strict) 
    ZEND_PARSE_PARAMETERS_END(); 
#endif 

    if (strict) { 
     ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) { 
      ZVAL_DEREF(entry); 
      if (fast_is_identical_function(value, entry)) { 
       if (behavior == 0) { 
        RETURN_TRUE; 
       } else { 
        if (str_idx) { 
         RETVAL_STR_COPY(str_idx); 
        } else { 
         RETVAL_LONG(num_idx); 
        } 
        return; 
       } 
      } 
     } ZEND_HASH_FOREACH_END(); 
    } else { 
     ZVAL_DEREF(value); 
     if (Z_TYPE_P(value) == IS_LONG) { 
      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) { 
       if (fast_equal_check_long(value, entry)) { 
        if (behavior == 0) { 
         RETURN_TRUE; 
        } else { 
         if (str_idx) { 
          RETVAL_STR_COPY(str_idx); 
         } else { 
          RETVAL_LONG(num_idx); 
         } 
         return; 
        } 
       } 
      } ZEND_HASH_FOREACH_END(); 
     } else if (Z_TYPE_P(value) == IS_STRING) { 
      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) { 
       if (fast_equal_check_string(value, entry)) { 
        if (behavior == 0) { 
         RETURN_TRUE; 
        } else { 
         if (str_idx) { 
          RETVAL_STR_COPY(str_idx); 
         } else { 
          RETVAL_LONG(num_idx); 
         } 
         return; 
        } 
       } 
      } ZEND_HASH_FOREACH_END(); 
     } else { 
      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) { 
       if (fast_equal_check_function(value, entry)) { 
        if (behavior == 0) { 
         RETURN_TRUE; 
        } else { 
         if (str_idx) { 
          RETVAL_STR_COPY(str_idx); 
         } else { 
          RETVAL_LONG(num_idx); 
         } 
         return; 
        } 
       } 
      } ZEND_HASH_FOREACH_END(); 
     } 
    } 

    RETURN_FALSE; 
} 
/* }}} */ 

/* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) 
    Checks if the given value exists in the array */ 
PHP_FUNCTION(in_array) 
{ 
    php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); 
} 
+2

私は通常downvoteはしませんが、私はこれをdownvoteする必要があります...私はコメントや説明の欠如を見過ごしても、これは関数の定義では、その定義が?iteration?のために 'ZEND_HASH_FOREACH_KEY_VAL'を使用するので、それがどのように動作するかは分かりません。それは受け入れられないはずです。私たちは実際にその機能が内部的にどのように機能するのか分かりません... –

関連する問題