先给大家介绍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_function
zend_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;
}
}
}
}
/* }}} */
【说明】:本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:)!