当前位置:首页 > PHP教程 > php高级应用 > 列表

深入php内核之php in array

发布:smiling 来源: PHP粉丝网  添加日期:2021-06-26 14:03:39 浏览: 评论:0 

这篇文章主要介绍了深入php内核之php in array的相关资料,需要的朋友可以参考下,先给大家介绍php in array函数基本知识热热身。

定义和用法

in_array() 函数在数组中搜索给定的值。

语法

in_array(value,array,type)

参数 描述

value 必需。规定要在数组搜索的值。

array 必需。规定要搜索的数组。

type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。

说明

如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。

如果没有在数组中找到参数,函数返回 false。

注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

无意中看到一段代码:

  1. <?php     
  2. $y="1800"
  3. $x = array(); 
  4. for($j=0;$j<50000;$j++){ 
  5.  $x[]= "{$j}"
  6. for($i=0;$i<30000;$i++){ 
  7.  if(in_array($y,$x)){ 
  8.   continue
  9.  }  

测试了一下

  1. [root@dev tmp]# time php b.php 
  2. real    0m9.517s 
  3. user    0m4.486s 
  4. 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 文件中

  1. /* }}} */              
  2. /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) 
  3.  Checks if the given value exists in the array */   
  4. PHP_FUNCTION(in_array)           
  5. {                 
  6.  php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);  
  7. }                 
  8. /* }}} */             
  9. /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict]) 
  10.  Searches the array for a given value and returns the corresponding key if successful */ 
  11. PHP_FUNCTION(array_search)          
  12. {             
  13.  php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);  
  14. }                 
  15. /* }}} */ 

顺便看到了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原型

  1. /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) 
  2.  * 0 = return boolean 
  3.  * 1 = return key 
  4.  */  
  5. static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */ 
  6. {   
  7.  zval *value,   /* value to check for */ 
  8.    *array,   /* array to check in */ 
  9.    **entry,   /* pointer to array entry */ 
  10.    res;    /* comparison result */ 
  11.  HashPosition pos;  /* hash iterator */ 
  12.  zend_bool strict = 0;  /* strict comparison or not */ 
  13.  ulong num_key; 
  14.  uint str_key_len; 
  15.  char *string_key; 
  16.  int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function; 
  17.  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) { 
  18.   return
  19.  }  
  20.  if (strict) { 
  21.   is_equal_func = is_identical_function; 
  22.  }  
  23.  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos); 
  24.  while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) { 
  25.   is_equal_func(&res, value, *entry TSRMLS_CC); 
  26.   if (Z_LVAL(res)) { 
  27.    if (behavior == 0) { 
  28.     RETURN_TRUE; 
  29.    } else { 
  30.     /* Return current key */ 
  31.     switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(array), &string_key, &str_key_len, &num_key, 0, &pos)) { 
  32.      case HASH_KEY_IS_STRING: 
  33.       RETURN_STRINGL(string_key, str_key_len - 1, 1); 
  34.       break
  35.      case HASH_KEY_IS_LONG: 
  36.       RETURN_LONG(num_key); 
  37.       break
  38.     } 
  39.    } 
  40.   } 
  41.   zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos); 
  42.  }  
  43.  RETURN_FALSE; 
  44. }   
  45. /* }}} */ 
  46. /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict]) 
  47.  Checks if the given value exists in the array */ 

我们发现 strict  这个值的不同有两种比较方式,看一下两个函数的不同之处

is_identical_function 检查类型是否相同

  1. ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 
  2. {   
  3.  Z_TYPE_P(result) = IS_BOOL
  4.  if (Z_TYPE_P(op1) != Z_TYPE_P(op2)) { 
  5.   Z_LVAL_P(result) = 0; 
  6.   return SUCCESS; 
  7.  }  
  8.  switch (Z_TYPE_P(op1)) { 
  9.   case IS_NULL
  10.    Z_LVAL_P(result) = 1; 
  11.    break
  12.   case IS_BOOL
  13.   case IS_LONG
  14.   case IS_RESOURCE
  15.    Z_LVAL_P(result) = (Z_LVAL_P(op1) == Z_LVAL_P(op2)); 
  16.    break
  17.   case IS_DOUBLE
  18.    Z_LVAL_P(result) = (Z_DVAL_P(op1) == Z_DVAL_P(op2)); 
  19.    break
  20.   case IS_STRING
  21.    Z_LVAL_P(result) = ((Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) 
  22.    && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)))); 
  23.    break
  24.   case IS_ARRAY
  25.    Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) 
  26.    zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0); 
  27.    break
  28.   case IS_OBJECT
  29.    if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) { 
  30.    Z_LVAL_P(result) = (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)); 
  31.    } else { 
  32.    Z_LVAL_P(result) = 0; 
  33.    } 
  34.    break
  35.   default
  36.    Z_LVAL_P(result) = 0; 
  37.    return FAILURE; 
  38.  }  
  39.  return SUCCESS; 
  40. }   
  41. /* }}} */ 

is_equal_function 不检查类型是否相同,所以需要隐式转换

  1. ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 
  2. {   
  3.  if (compare_function(result, op1, op2 TSRMLS_CC) == FAILURE) { 
  4.   return FAILURE; 
  5.  }  
  6.  ZVAL_BOOL(result, (Z_LVAL_P(result) == 0)); 
  7.  return SUCCESS; 
  8. }   
  9. /* }}} */ 
  10. ==》compare_function 
  11.  
  12. ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ 
  13. {    
  14.  int ret; 
  15.  int converted = 0; 
  16.  zval op1_copy, op2_copy; 
  17.  zval *op_free; 
  18.  while (1) { 
  19.   switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) { 
  20.    case TYPE_PAIR(IS_LONGIS_LONG): 
  21.    ZVAL_LONG(result, Z_LVAL_P(op1)>Z_LVAL_P(op2)?1:(Z_LVAL_P(op1)<Z_LVAL_P(op2)?-1:0)); 
  22.    return SUCCESS; 
  23.    case TYPE_PAIR(IS_DOUBLEIS_LONG): 
  24.    Z_DVAL_P(result) = Z_DVAL_P(op1) - (double)Z_LVAL_P(op2); 
  25.    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 
  26.    return SUCCESS; 
  27.    case TYPE_PAIR(IS_LONGIS_DOUBLE): 
  28.    Z_DVAL_P(result) = (double)Z_LVAL_P(op1) - Z_DVAL_P(op2); 
  29.    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 
  30.    return SUCCESS; 
  31.    case TYPE_PAIR(IS_DOUBLEIS_DOUBLE): 
  32.    if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { 
  33.     ZVAL_LONG(result, 0); 
  34.    } else { 
  35.     Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); 
  36.     ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); 
  37.    } 
  38.    return SUCCESS; 
  39.    case TYPE_PAIR(IS_ARRAYIS_ARRAY): 
  40.    zend_compare_arrays(result, op1, op2 TSRMLS_CC); 
  41.    return SUCCESS; 
  42.    case TYPE_PAIR(IS_NULLIS_NULL): 
  43.    ZVAL_LONG(result, 0); 
  44.    return SUCCESS; 
  45.    case TYPE_PAIR(IS_NULLIS_BOOL): 
  46.    ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0); 
  47.    return SUCCESS; 
  48.    case TYPE_PAIR(IS_BOOLIS_NULL): 
  49.    ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0); 
  50.    return SUCCESS; 
  51.    case TYPE_PAIR(IS_BOOLIS_BOOL): 
  52.    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 
  53.    return SUCCESS; 
  54.    case TYPE_PAIR(IS_STRINGIS_STRING): 
  55.    zendi_smart_strcmp(result, op1, op2); 
  56.    return SUCCESS; 
  57.    case TYPE_PAIR(IS_NULLIS_STRING): 
  58.    ZVAL_LONG(result, zend_binary_strcmp("", 0, Z_STRVAL_P(op2), Z_STRLEN_P(op2))); 
  59.    return SUCCESS; 
  60.    case TYPE_PAIR(IS_STRINGIS_NULL): 
  61.    ZVAL_LONG(result, zend_binary_strcmp(Z_STRVAL_P(op1), Z_STRLEN_P(op1), "", 0)); 
  62.    return SUCCESS; 
  63.    case TYPE_PAIR(IS_OBJECTIS_NULL): 
  64.    ZVAL_LONG(result, 1); 
  65.    return SUCCESS; 
  66.    case TYPE_PAIR(IS_NULLIS_OBJECT): 
  67.    ZVAL_LONG(result, -1); 
  68.    return SUCCESS; 
  69.    case TYPE_PAIR(IS_OBJECTIS_OBJECT): 
  70.    /* If both are objects sharing the same comparision handler then use is */ 
  71.    if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) { 
  72.     if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) { 
  73.      /* object handles are identical, apparently this is the same object */ 
  74.      ZVAL_LONG(result, 0); 
  75.      return SUCCESS; 
  76.     } 
  77.     ZVAL_LONG(result, Z_OBJ_HT_P(op1)->compare_objects(op1, op2 TSRMLS_CC)); 
  78.     return SUCCESS; 
  79.    } 
  80.    /* break missing intentionally */ 
  81.    default
  82.    if (Z_TYPE_P(op1) == IS_OBJECT) { 
  83.     if (Z_OBJ_HT_P(op1)->get) { 
  84.      op_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); 
  85.      ret = compare_function(result, op_free, op2 TSRMLS_CC); 
  86.      zend_free_obj_get_result(op_free TSRMLS_CC); 
  87.      return ret; 
  88.     } else if (Z_TYPE_P(op2) != IS_OBJECT && Z_OBJ_HT_P(op1)->cast_object) { 
  89.      ALLOC_INIT_ZVAL(op_free); 
  90.      if (Z_OBJ_HT_P(op1)->cast_object(op1, op_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) { 
  91.       ZVAL_LONG(result, 1); 
  92.       zend_free_obj_get_result(op_free TSRMLS_CC); 
  93.       return SUCCESS; 
  94.      } 
  95.      ret = compare_function(result, op_free, op2 TSRMLS_CC); 
  96.      zend_free_obj_get_result(op_free TSRMLS_CC); 
  97.      return ret; 
  98.     } 
  99.    } 
  100.    if (Z_TYPE_P(op2) == IS_OBJECT) { 
  101.     if (Z_OBJ_HT_P(op2)->get) { 
  102.      op_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); 
  103.      ret = compare_function(result, op1, op_free TSRMLS_CC); 
  104.      zend_free_obj_get_result(op_free TSRMLS_CC); 
  105.      return ret; 
  106.     } else if (Z_TYPE_P(op1) != IS_OBJECT && Z_OBJ_HT_P(op2)->cast_object) { 
  107.      ALLOC_INIT_ZVAL(op_free); 
  108.      if (Z_OBJ_HT_P(op2)->cast_object(op2, op_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) { 
  109.       ZVAL_LONG(result, -1); 
  110.       zend_free_obj_get_result(op_free TSRMLS_CC); 
  111.       return SUCCESS; 
  112.      } 
  113.      ret = compare_function(result, op1, op_free TSRMLS_CC); 
  114.      zend_free_obj_get_result(op_free TSRMLS_CC); 
  115.      return ret; 
  116.     } else if (Z_TYPE_P(op1) == IS_OBJECT) { 
  117.      ZVAL_LONG(result, 1); 
  118.      return SUCCESS; 
  119.     } 
  120.    } 
  121.    if (!converted) { 
  122.     if (Z_TYPE_P(op1) == IS_NULL) { 
  123.      zendi_convert_to_boolean(op2, op2_copy, result); 
  124.      ZVAL_LONG(result, Z_LVAL_P(op2) ? -1 : 0); 
  125.      return SUCCESS; 
  126.     } else if (Z_TYPE_P(op2) == IS_NULL) { 
  127.      zendi_convert_to_boolean(op1, op1_copy, result); 
  128.      ZVAL_LONG(result, Z_LVAL_P(op1) ? 1 : 0); 
  129.      return SUCCESS; 
  130.     } else if (Z_TYPE_P(op1) == IS_BOOL) { 
  131.      zendi_convert_to_boolean(op2, op2_copy, result); 
  132.      ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 
  133.      return SUCCESS; 
  134.     } else if (Z_TYPE_P(op2) == IS_BOOL) { 
  135.      zendi_convert_to_boolean(op1, op1_copy, result); 
  136.      ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(op1) - Z_LVAL_P(op2))); 
  137.      return SUCCESS; 
  138.     } else { 
  139.      zendi_convert_scalar_to_number(op1, op1_copy, result); 
  140.      zendi_convert_scalar_to_number(op2, op2_copy, result); 
  141.      converted = 1; 
  142.     } 
  143.    } else if (Z_TYPE_P(op1)==IS_ARRAY) { 
  144.     ZVAL_LONG(result, 1); 
  145.     return SUCCESS; 
  146.    } else if (Z_TYPE_P(op2)==IS_ARRAY) { 
  147.     ZVAL_LONG(result, -1); 
  148.     return SUCCESS; 
  149.    } else if (Z_TYPE_P(op1)==IS_OBJECT) { 
  150.     ZVAL_LONG(result, 1); 
  151.     return SUCCESS; 
  152.    } else if (Z_TYPE_P(op2)==IS_OBJECT) { 
  153.     ZVAL_LONG(result, -1); 
  154.     return SUCCESS; 
  155.    } else { 
  156.     ZVAL_LONG(result, 0); 
  157.     return FAILURE; 
  158.    } 
  159.   }  
  160.  }   
  161. }    
  162. /* }}} */

Tags: php内核 php in array

分享到: