深入php核心之php in array_php執行個體

來源:互聯網
上載者:User

先給大家介紹php in array函數基本知識熱熱身。

定義和用法

in_array() 函數在數組中搜尋給定的值。

文法
in_array(value,array,type)

參數 描述
value 必需。規定要在數組搜尋的值。
array 必需。規定要搜尋的數組。
type 可選。如果設定該參數為 true,則檢查搜尋的資料與數組的值的類型是否相同。

 說明

如果給定的值 value 存在於數組 array 中則返回 true。如果第三個參數設定為 true,函數只有在元素存在於數組中且資料類型與給定值相同時才返回 true。

如果沒有在數組中找到參數,函數返回 false。

注釋:如果 value 參數是字串,且 type 參數設定為 true,則搜尋區分大小寫。

無意中看到一段代碼

<?php    $y="1800";$x = array();for($j=0;$j<50000;$j++){ $x[]= "{$j}";}for($i=0;$i<30000;$i++){ if(in_array($y,$x)){  continue; } }

測試了一下

[root@dev tmp]# time php b.php
real    0m9.517s
user    0m4.486s
sys     0m0.015s

竟然需要9s

in_array是這個樣子的

複製代碼 代碼如下:

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

在 haystack 中搜尋 needle,如果沒有設定 strict 則使用寬鬆的比較。

needle

待搜尋的值。如果 needle 是字串,則比較是區分大小寫。

haystack

這個數組。

strict

如果第三個參數 strict 的值為 TRUE 則 in_array() 函數還會檢查 needle 的類型是否和 haystack 中的相同。

那麼我看一下原始碼

第一步 在ext/standard/array.c 檔案中

/* }}} */              /* {{{ 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); }                /* }}} */             /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict]) Searches the array for a given value and returns the corresponding key if successful */PHP_FUNCTION(array_search)         {             php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); }                /* }}} */ 

順便看到了array_search,原來和in_array的內部實現基本一致

其中函數的參數 在./zend.h中

#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC

第二步 在ext/standard/array.c 檔案中 查看php_search_array原型

/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) * 0 = return boolean * 1 = return key */  static 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 */   res;    /* comparison result */ HashPosition pos;  /* hash iterator */ zend_bool strict = 0;  /* strict comparison or not */ ulong num_key; uint str_key_len; char *string_key; int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {  return; }  if (strict) {  is_equal_func = is_identical_function; }  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {  is_equal_func(&res, value, *entry TSRMLS_CC);  if (Z_LVAL(res)) {   if (behavior == 0) {    RETURN_TRUE;   } else {    /* Return current key */    switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) {     case HASH_KEY_IS_STRING:      RETURN_STRINGL(string_key, str_key_len - 1, 1);      break;     case HASH_KEY_IS_LONG:      RETURN_LONG(num_key);      break;    }   }  }  zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); }  RETURN_FALSE;}  /* }}} *//* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) Checks if the given value exists in the array */

我們發現 strict  這個值的不同有兩種比較方式,看一下兩個函數的不同之處

is_identical_function 檢查類型是否相同

ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{   Z_TYPE_P(result) = IS_BOOL; if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) {  Z_LVAL_P(result) = 0;  return SUCCESS; }  switch (Z_TYPE_P(op1)) {  case IS_NULL:   Z_LVAL_P(result) = 1;   break;  case IS_BOOL:  case IS_LONG:  case IS_RESOURCE:   Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2));   break;  case IS_DOUBLE:   Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2));   break;  case IS_STRING:   Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2))   && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1))));   break;  case IS_ARRAY:   Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2)   zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0);   break;  case IS_OBJECT:   if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) {   Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2));   } else {   Z_LVAL_P(result) = 0;   }   break;  default:   Z_LVAL_P(result) = 0;   return FAILURE; }  return SUCCESS;}  /* }}} */

is_equal_function 不檢查類型是否相同,所以需要隱式轉換

ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{   if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) {  return FAILURE; }  ZVAL_BOOL(result, (Z_LVAL_P(result) == 0)); return SUCCESS;}  /* }}} */==》compare_functionZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */{    int ret; int converted = 0; zval op1_copy, op2_copy; zval *op_free; while (1) {  switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {   case TYPE_PAIR(IS_LONG, IS_LONG):   ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0));   return SUCCESS;   case TYPE_PAIR(IS_DOUBLE, IS_LONG):   Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2);   ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));   return SUCCESS;   case TYPE_PAIR(IS_LONG, IS_DOUBLE):   Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2);   ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));   return SUCCESS;   case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):   if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) {    ZVAL_LONG(result, 0);   } else {    Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2);    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result)));   }   return SUCCESS;   case TYPE_PAIR(IS_ARRAY, IS_ARRAY):   zend_compare_arrays(result, op1, op2 TSRMLS_CC);   return SUCCESS;   case TYPE_PAIR(IS_NULL, IS_NULL):   ZVAL_LONG(result, 0);   return SUCCESS;   case TYPE_PAIR(IS_NULL, IS_BOOL):   ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);   return SUCCESS;   case TYPE_PAIR(IS_BOOL, IS_NULL):   ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);   return SUCCESS;   case TYPE_PAIR(IS_BOOL, IS_BOOL):   ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));   return SUCCESS;   case TYPE_PAIR(IS_STRING, IS_STRING):   zendi_smart_strcmp(result, op1, op2);   return SUCCESS;   case TYPE_PAIR(IS_NULL, IS_STRING):   ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2)));   return SUCCESS;   case TYPE_PAIR(IS_STRING, IS_NULL):   ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0));   return SUCCESS;   case TYPE_PAIR(IS_OBJECT, IS_NULL):   ZVAL_LONG(result, 1);   return SUCCESS;   case TYPE_PAIR(IS_NULL, IS_OBJECT):   ZVAL_LONG(result, -1);   return SUCCESS;   case TYPE_PAIR(IS_OBJECT, IS_OBJECT):   /* If both are objects sharing the same comparision handler then use is */   if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) {    if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) {     /* object handles are identical, apparently this is the same object */     ZVAL_LONG(result, 0);     return SUCCESS;    }    ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC));    return SUCCESS;   }   /* break missing intentionally */   default:   if (Z_TYPE_P(op1) == IS_OBJECT) {    if (Z_OBJ_HT_P(op1)->get) {     op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC);     ret = compare_function(result, op_free, op2 TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) {     ALLOC_INIT_ZVAL(op_free);     if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) {      ZVAL_LONG(result, 1);      zend_free_obj_get_result(op_free TSRMLS_CC);      return SUCCESS;     }     ret = compare_function(result, op_free, op2 TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    }   }   if (Z_TYPE_P(op2) == IS_OBJECT) {    if (Z_OBJ_HT_P(op2)->get) {     op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC);     ret = compare_function(result, op1, op_free TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) {     ALLOC_INIT_ZVAL(op_free);     if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) {      ZVAL_LONG(result, -1);      zend_free_obj_get_result(op_free TSRMLS_CC);      return SUCCESS;     }     ret = compare_function(result, op1, op_free TSRMLS_CC);     zend_free_obj_get_result(op_free TSRMLS_CC);     return ret;    } else if (Z_TYPE_P(op1) == IS_OBJECT) {     ZVAL_LONG(result, 1);     return SUCCESS;    }   }   if (!converted) {    if (Z_TYPE_P(op1) == IS_NULL) {     zendi_convert_to_boolean(op2, op2_copy, result);     ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0);     return SUCCESS;    } else if (Z_TYPE_P(op2) == IS_NULL) {     zendi_convert_to_boolean(op1, op1_copy, result);     ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0);     return SUCCESS;    } else if (Z_TYPE_P(op1) == IS_BOOL) {     zendi_convert_to_boolean(op2, op2_copy, result);     ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));     return SUCCESS;    } else if (Z_TYPE_P(op2) == IS_BOOL) {     zendi_convert_to_boolean(op1, op1_copy, result);     ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2)));     return SUCCESS;    } else {     zendi_convert_scalar_to_number(op1, op1_copy, result);     zendi_convert_scalar_to_number(op2, op2_copy, result);     converted = 1;    }   } else if (Z_TYPE_P(op1)==IS_ARRAY) {    ZVAL_LONG(result, 1);    return SUCCESS;   } else if (Z_TYPE_P(op2)==IS_ARRAY) {    ZVAL_LONG(result, -1);    return SUCCESS;   } else if (Z_TYPE_P(op1)==IS_OBJECT) {    ZVAL_LONG(result, 1);    return SUCCESS;   } else if (Z_TYPE_P(op2)==IS_OBJECT) {    ZVAL_LONG(result, -1);    return SUCCESS;   } else {    ZVAL_LONG(result, 0);    return FAILURE;   }  }  }  }   /* }}} */

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.