首页 后端开发 php教程 PHP源代码数组统计count分析_php技巧

PHP源代码数组统计count分析_php技巧

May 17, 2016 am 09:16 AM
count 数组统计

zend给php的所有变量都用结构的方式去保存,而字符串的保存和数组的保存也是不同的,数组采用的是hash表的方式去保存(大家知道hash保存的地址有效的减少冲突-hash散列表的概念你懂的),而在php中的结构体上表现如下:

复制代码 代码如下:

//文件1:zend/zend.h
/*
* zval
*/
typedef struct _zval_struct zval;
...
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;

struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
//hash表的结构如下
//文件2:zend/zend_hash.h
typedef struct _hashtable {
uint nTableSize;
uint nTableMask;
uint nNumOfElements;
ulong nNextFreeElement;
Bucket *pInternalPointer; /* Used for element traversal */
Bucket *pListHead;
Bucket *pListTail;
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
int inconsistent;
#endif
}
HashTable;

一般的变量(字符串)在使用strlen获取长度的时候,其实获取的就是zvalue_value.str这个结构中的len属性,效率上O(1)次,特别说明的一点是:strlen在php中并没有核心的实现,而是在使用了zend中的宏定义来获取:

复制代码 代码如下:

//文件3:zend/zend_operators.php
#define Z_STRLEN(zval) (zval).value.str.len
...
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
...
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)

而对于数组的count操作,其实有两种结果,在count 的api中也提到了第二个参数mode《http://www.php.net/manual/en/function.count.php》,这个mode参数指明了,是否需要重新统计,而它的重新统计将会遍历一次数组,效率上是O(N)[N:长度],默认情况下是不重新统计,那这个时候将会直接输出hashtable中的nNumOfElements,此时的效率也是O(1)次:count代码如下:
复制代码 代码如下:

//文件4:ext/standard/array.c
PHP_FUNCTION(count)
{
zval *array;
long mode = COUNT_NORMAL;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &mode) == FAILURE) {
return;
}

switch (Z_TYPE_P(array)) {
case IS_NULL:
RETURN_LONG(0);
break;
case IS_ARRAY:
RETURN_LONG (php_count_recursive (array, mode TSRMLS_CC));
break;
.....

//php_count_recursive的实现
static int php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */
{
long cnt = 0;
zval **element;

if (Z_TYPE_P(array) == IS_ARRAY) {
//错误处理
if (Z_ARRVAL_P(array)->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
return 0;
}
//通过zend_hash_num_elements直接获得长度
cnt = zend_hash_num_elements(Z_ARRVAL_P(array));

//如果指定了需要重新统计,则会进入一次循环统计
if (mode == COUNT_RECURSIVE) {
HashPosition pos;

for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
) {
Z_ARRVAL_P(array)->nApplyCount++;
cnt += php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC);
Z_ARRVAL_P(array)->nApplyCount--;
}
}
}

return cnt;
}

//文件5:zend/zend_hash.c
//zend_hash_num_elements的实现
ZEND_API int zend_hash_num_elements(const HashTable *ht)
{
IS_CONSISTENT(ht);

return ht->nNumOfElements;
}
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

counta和count的区别 counta和count的区别 Nov 20, 2023 am 10:01 AM

Count函数用于计算指定范围内数字的个数。它忽略文本、逻辑值和空值,但会将空单元格计算在内,Count函数只计算包含实际数字的单元格数量。而CountA函数用于计算指定范围内非空单元格的个数。它不仅计算包含实际数字的单元格,还计算包含文本、逻辑值和公式等非空单元格的数量。

如何使用PHP中的array_count_values函数统计数组中每个值出现的次数 如何使用PHP中的array_count_values函数统计数组中每个值出现的次数 Jun 26, 2023 pm 02:12 PM

在PHP中,我们经常需要对数组进行各种操作,统计数组中每个值出现的次数是其中一个常见的需求。PHP提供了一个简单且高效的函数——array_count_values,可以轻松地完成这个任务。array_count_values函数的语法如下:array_count_values(array$array)这个函数接收一个数组参数,返回一个新的数组,其中包含原

MySQL关于Count函数的用法区别总结 MySQL关于Count函数的用法区别总结 Nov 29, 2022 pm 04:47 PM

本文给大家介绍MySQL关于Count函数的用法区别,统计数据的需求在我们日常开发中是非常容易遇到了,MySQL也支持多种的计算的函数,接下来我们来看一看他们之间有什么区别,以及他们是否存在一些坑。

php中count函数的用法是什么 php中count函数的用法是什么 Sep 09, 2021 pm 05:08 PM

php中count函数的用法是:【count(array,mode);】,其中参数array规定要计数的数组,参数mode规定函数的模式。

mysql踩坑之count distinct多列问题怎么解决 mysql踩坑之count distinct多列问题怎么解决 Jun 03, 2023 am 10:49 AM

复现的测试数据库如下所示:CREATETABLE`test_distinct`(`id`int(11)NOTNULLAUTO_INCREMENT,`a`varchar(50)CHARACTERSETutf8DEFAULTNULL,`b`varchar(50)CHARACTERSETutf8DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=latin1;表内测试数据如下,现在我们需要统计这三列去重后的列

PHP函数介绍—array_count_values(): 统计数组中每个元素的出现次数 PHP函数介绍—array_count_values(): 统计数组中每个元素的出现次数 Jul 25, 2023 pm 07:18 PM

PHP函数介绍—array_count_values():统计数组中每个元素的出现次数在PHP的开发中,经常会遇到需要对数组中的元素进行统计的情况。PHP提供了一些方便的函数来帮助我们实现这个目标,其中之一就是array_count_values()函数。array_count_values()函数能够统计数组中每个元素的出现次数,并返回一个关联数组,其中

学习使用PHP count()函数计算数组元素个数 学习使用PHP count()函数计算数组元素个数 Jun 27, 2023 am 10:37 AM

PHP是一种非常流行的服务器端编程语言,它具有强大的开发能力,尤其是在在数组操作方面。PHP中的数组(array)被广泛使用,具有存储和管理多个数据项的能力。在对数组进行操作时,经常需要计算数组中元素的个数,此时可以通过使用PHP中的count()函数来实现。count()函数是PHP内置的计算数组元素个数的函数。在使用该函数时,只需要将数组作为函数的参数传

java Count怎么计算流中的元素 java Count怎么计算流中的元素 May 11, 2023 pm 04:07 PM

说明1、count是终端操作,可以统计stream流中的元素总数,返回值为long类型。2、count()返回流中元素的计数。这是归纳的特殊情况(归纳运算采用一系列输入元素,通过重复应用组合运算将其组合成一个总结结果)。这是终端操作,可能会产生结果和副作用。执行终端操作后,管道被视为消耗,无法再利用。实例//验证list中string是否有以a开头的,匹配到第一个,即返回truebooleananyStartsWithA=stringCollection.stream().anyMatch((s

See all articles