Analysis of array_keys and array_unique function source code in PHP, arraykeys_PHP tutorial

Source: Internet
Author: User
Analysis of array_keys and array_unique function source code in PHP, arraykeys. In PHP, array_keys and array_unique function source code are analyzed. arraykeys performance analysis analyzes the running performance and looks at the following test code: $ testarray (); for ($ run0; $ run10000; $ run ++) analysis of array_keys and array_unique function source code in PHP, arraykeys

Performance analysis

Analyze the running performance to see the following test code:

$test=array();for($run=0; $run<10000; $run++)$test[]=rand(0,100);$time=microtime(true);$out = array_unique($test);$time=microtime(true)-$time;echo 'Array Unique: '.$time."\n";$time=microtime(true);$out=array_keys(array_flip($test));$time=microtime(true)-$time;echo 'Keys Flip: '.$time."\n";$time=microtime(true);$out=array_flip(array_flip($test));$time=microtime(true)-$time;echo 'Flip Flip: '.$time."\n";

The running result is as follows:

As you can see, the array_unique function requires 0.069 s, the array_flip function requires 0.00152 s, and the array_keys function requires 0.00146 s. The array_flip function requires s.

The test results show that calling the array_keys function after array_flip is faster than the array_unique function. So what are the specific reasons? Let's see how these two functions are implemented at the bottom layer of PHP.

Source Code Analysis

/* {Proto array array_keys (array input [, mixed search_value [, bool strict]) Return just the keys from the input array, optionally only for the specified search_value */PHP_FUNCTION (array_keys) {// variable definition zval * input,/* Input array */* search_value = NULL, /* Value to search for */** entry,/* An entry in the input array */res,/* Result of comparison */* new_val; /* New value */int add_key ;/* Flag to indicate whether a key shoshould be added */char * string_key;/* String key */uint string_key_len; ulong num_key;/* Numeric key */zend_bool strict = 0; /* do strict comparison */HashPosition pos; int (* is_wash_func) (zval *, zval *, zval * TSRMLS_DC) = is_wash_function; // if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a | zb", & input, & search_value, & strict) = FAILURE) {r Eturn;} // if strict is true, set is_assist_func to is_identical_function, that is, if (strict) {is_assist_func = is_identical_function ;} /* initialize the returned array size based on search_vale */if (search_value! = NULL) {array_init (return_value);} else {array_init_size (return_value, zend_hash_num_elements (Z_ARRVAL_P (input);} add_key = 1;/* traverses input array parameters, then add the key value to the returned array */struct (Z_ARRVAL_P (input), & pos); // reset the pointer // cyclically traverse the array while (zend_hash_get_current_data_ex (Z_ARRVAL_P (input ), (void **) & entry, & pos) = SUCCESS) {// if search_value is not empty if (search_value! = NULL) {// Determine whether search_value is the same as the current value, and save the comparison result to the add_key variable is_1__func (& res, search_value, * entry TSRMLS_CC ); add_key = zval_is_true (& res);} if (add_key) {// Create a zval struct MAKE_STD_ZVAL (new_val ); // Insert the value to return_value based on whether the key value is a string or an integer. switch (zend_hash_get_current_key_ex (Z_ARRVAL_P (input), & string_key, & string_key_len, & num_key, 1 )) {case HASH_KEY_IS_STRING: ZVAL_STRINGL (new_val, string_key, string_key_len-1, 0); // This function inserts the value into return_value. if the key value already exists, use the new value to update the corresponding value. otherwise, insert values (Z_ARRVAL_P (return_value), & new_val, sizeof (zval *), NULL); break; case HASH_KEY_IS_LONG: Z_TYPE_P (new_val) = IS_LONG; Z_LVAL_P (new_val) = num_key; zend_hash_next_index_insert (Z_ARRVAL_P (return_value), & new_val, sizeof (zval *), NULL); break ;}} // move to the next zend_hash_move_forward_ex (Z_ARRVAL_P (input), & pos );}}/*}}}*/

The above is the underlying source code of the array_keys function. For ease of understanding, I have added some Chinese notes. To view the original code, click here. This function creates a temporary array and copies key-value pairs to the new array. if duplicate key-value pairs appear during the replication process, replace them with new values. The main steps of this function are to call the zend_hash_next_index_insert function in rows 57 and 63. This function inserts elements into the array. if repeated values exist, the new value is used to update the value pointed to by the original key value. Otherwise, the new value is inserted directly. The time complexity is O (n ).

/* {Proto array array_flip (array input) Return array with key <-> value flipped */PHP_FUNCTION (array_flip) {// defines the variable zval * array, ** entry, * data; char * string_key; uint str_key_len; ulong num_key; HashPosition pos; // Parse the array parameter if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a", & array) = FAILURE) {return;} // initialize the returned array array_init_size (return_value, zend_hash_num_elements (Z_ARRVAL_P (array ))); // Reset the pointer cursor (Z_ARRVAL_P (array), & pos); // traverses each element and performs the key <-> value exchange operation while (zend_hash_get_current_data_ex (Z_ARRVAL_P (array ), (void **) & entry, & pos) = SUCCESS) {// initialize a struct MAKE_STD_ZVAL (data ); // assign the value of the original array to the switch (keys (Z_ARRVAL_P (array), & string_key, & str_key_len, & num_key, 1, & pos) of the new array. {case HASH_KEY_IS_STRING: ZVAL_STRINGL (data, string_key, s Tr_key_len-1, 0); break; case HASH_KEY_IS_LONG: Z_TYPE_P (data) = IS_LONG; Z_LVAL_P (data) = num_key; break ;} // assign the key value of the original array to the value of the new array. if there are duplicates, use the new value to overwrite the old value if (Z_TYPE_PP (entry) = IS_LONG) {zend_hash_index_update (Z_ARRVAL_P (return_value), Z_LVAL_PP (entry), & data, sizeof (data), NULL);} else if (Z_TYPE_PP (entry) = IS_STRING) {zend_symtable_update (Z_ARRVAL_P (return_value), Z_STRVAL_PP (entry), Z_STRLEN_PP (e Ntry) + 1, & data, sizeof (data), NULL);} else {zval_ptr_dtor (& data);/* will free also zval structure */php_error_docref (NULL TSRMLS_CC, e_WARNING, "Can only flip STRING and INTEGER values! ");} // The next zend_hash_move_forward_ex (Z_ARRVAL_P (array), & pos );}}/*}}}*/

The above is the source code of the array_flip function. Click the link to view the original code. The main task of this function is to create a new array and traverse the original array. At the beginning of 26 rows, assign the value of the original array to the key of the new array, and then assign the key of the original array to the value of the new array at the beginning of 37 rows. if there are repeated values, overwrite the old value with the new value. The time complexity of the entire function is O (n ). Therefore, the time complexity of using array_keys after array_flip is O (n ).

Next, let's look at the source code of the array_unique function. Click the link to view the original code.

/* {Proto array array_unique (array input [, int sort_flags]) Removes duplicate values from array */PHP_FUNCTION (array_unique) {// defines the variable zval * array, * tmp; bucket * p; struct bucketindex {Bucket * B; unsigned int I;}; struct bucketindex * arTmp, * cmpdata, * lastkept; unsigned int I; long sort_type = PHP_SORT_STRING; // Parse the parameter if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "a | l", & array, & sort_ty Pe) = FAILURE) {return ;}// set the comparison function struct (sort_type TSRMLS_CC); // The array array_init_size (return_value, zend_hash_num_elements (Z_ARRVAL_P (array) is returned ))); // Copy the value to the new array zend_hash_copy (Z_ARRVAL_P (return_value), Z_ARRVAL_P (array), (optional) zval_add_ref, (void *) & tmp, sizeof (zval *)); if (Z_ARRVAL_P (array)-> nNumOfElements <= 1) {/* do nothing */return;}/* create an array based on the target_hash buckets pointer And sort */arTmp = (struct bucketindex *) pemalloc (Z_ARRVAL_P (array)-> nNumOfElements + 1) * sizeof (struct bucketindex), Z_ARRVAL_P (array)-> persistent ); if (! ArTmp) {zval_dtor (return_value); RETURN_FALSE;} for (I = 0, p = Z_ARRVAL_P (array)-> pListHead; p; I ++, p = p-> pListNext) {arTmp [I]. B = p; arTmp [I]. I = I;} arTmp [I]. B = NULL; // sort zend_qsort (void *) arTmp, I, sizeof (struct bucketindex), php_array_data_compare TSRMLS_CC);/* traverse the sorted array, then delete the repeated elements */lastkept = arTmp; for (cmpdata = arTmp + 1; cmpdata-> B; cmpdata ++) {if (php_array_data_compare (lastkept, cmpdata TSRMLS_CC )) {lastkept = cmpdata;} else {if (lastkept-> I> cmpdata-> I) {p = lastkept-> B; lastkept = cmpdata ;} else {p = cmpdata-> B;} if (p-> nKeyLength = 0) {zend_hash_index_del (Z_ARRVAL_P (return_value), p-> h );} else {if (Z_ARRVAL_P (return_value) ==& EG (symbol_table) {zend_delete_global_variable (p-> arKey, p-> nKeyLength-1 TSRMLS_CC );} else {zend_hash_quick_del (Z_ARRVAL_P (return_value), p-> arKey, p-> nKeyLength, p-> h) ;}}} pefree (arTmp, Z_ARRVAL_P (array) -> persistent );}/*}}}*/

We can see that this function initializes a new array, copies the value to the new array, and then calls the sorting function in row 45 to sort the array, the sorting algorithm is the block tree sorting algorithm of the zend Engine. Next, traverse the sorted array and delete repeated elements. The largest overhead of the entire function is called the sorting function, and the time complexity of the fast sort is O (nlogn). Therefore, the time complexity of this function is O (nlogn ).

Conclusion

Array_unique calls the quick sort algorithm at the underlying layer, which increases the time overhead of function running, resulting in slow operation of the entire function. This is why array_keys is faster than the array_unique function.

Articles you may be interested in:
  • Php checks whether the same value array_unique exists in the array.
  • Note the json_encode after php array_unique
  • Php array function sequence of array_unique ()-remove repeated element values from the array
  • Array_keys () of the php array function sequence-get the array key name
  • PHP obtains the position of an element in the array and array_keys function application

Analyze the runtime performance and look at the following test code: $ test = array (); for ($ run = 0; $ run10000; $ run ++ )...

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.