PHP内置函数分析之array_chunk
作者 斯人 | 发布于 2012 年 2 月 27 日
PHP PHP内核

array_chunk函数:
array_chunk(array $arr,int size,bool);
将 数组$arra按size大小切割成多个,如果 bool为真,则保留原来的键值,为假 则从0开始重建索引

<!php
$input_array = array('a', 'b', 'c', 'd', 'e');
print_r(array_chunk($input_array, 2));
print_r(array_chunk($input_array, 2, true)); ?>

结果如下:

Array
(
[0] => Array
(
[0] => a
[1] => b
)

[1] => Array
(
[0] => c
[1] => d
)

[2] => Array
(
[0] => e
)

)
Array
(
[0] => Array
(
[0] => a
[1] => b
)

[1] => Array
(
[2] => c
[3] => d
)

[2] => Array
(
[4] => e
)

)
来看看内核源码:

PHP_FUNCTION(array_chunk)
{
        int argc = ZEND_NUM_ARGS(), key_type, num_in;
        long size, current = 0; 
        char *str_key;
        uint str_key_len;
        zval *input = NULL;
        zval *chunk = NULL;
        zval **entry;
        HashPosition pos; 

        if (zend_parse_parameters(argc TSRMLS_CC, "al|b", &input, &size, &preserve_keys) == FAILURE) {                return;
        }            
        /* Do bounds checking for size parameter. */
        if (size < 1) {
                return;
        }
       //获取数组元素个数
        num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
         //如果分割的个数大于 数组的元素
        if (size > num_in) {
                最小为1
                size = num_in > 0 ? num_in : 1;
        }
        //初始化返回值return_value
        array_init_size(return_value, ((num_in - 1) / size) + 1);
        //数组当前执行的元素指针
        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);
        while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void**)&entry, &pos) == SUCCESS) {
                /* If new chunk, create and initialize it. */
                if (!chunk) {
                        MAKE_STD_ZVAL(chunk);
                        array_init_size(chunk, size);
                }
                zval_add_ref(entry);
                if (preserve_keys) { //如果保存原来的键值
                         //获取当前指针的key
                         key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &str_key, &str_key_len, &num_key, 0, &pos);
                        switch (key_type) {
                                case HASH_KEY_IS_STRING://键值是字符串,将key和值添加到chunk里
                                        add_assoc_zval_ex(chunk, str_key, str_key_len, *entry);
                                        break;
                                default:
                                        add_index_zval(chunk, num_key, *entry);
                                        break;
                        }
                } else {//重建数组索引 只将entry数据添加到chunki里
                        add_next_index_zval(chunk, *entry);
                }

                /* If reached the chunk size, add it to the result array, and reset the
                 * pointer. */
                if (!(++current % size)) {
                        add_next_index_zval(return_value, chunk);
                        chunk = NULL;
                }
                //移动到下一元素
                zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);
        }

        /* Add the final chunk if there is one. */
       //添加到返回值return_value的Hash里
        if (chunk) {
                add_next_index_zval(return_value, chunk);
        }
}
原文出处:http://www.imsiren.com/archives/274