ホームページ バックエンド開発 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 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

カウンタとカウントの違い カウンタとカウントの違い Nov 20, 2023 am 10:01 AM

Count 関数は、指定された範囲内の数値の数をカウントするために使用されます。テキスト、論理値、NULL 値は無視されますが、空のセルはカウントされます。Count 関数は、実際の数値を含むセルの数のみをカウントします。 CountA 関数は、指定された範囲内の空でないセルの数をカウントするために使用されます。実際の数値を含むセルを数えるだけでなく、テキスト、論理値、数式を含む空でないセルの数も数えます。

PHPのarray_count_values関数を使用して、配列内の各値の出現数をカウントする方法 PHPのarray_count_values関数を使用して、配列内の各値の出現数をカウントする方法 Jun 26, 2023 pm 02:12 PM

PHP では、配列に対してさまざまな操作を実行する必要がよくありますが、配列内の各値の出現回数をカウントすることは、一般的なニーズの 1 つです。 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 は関数のモードを指定します。

PHP 関数の紹介—array_count_values(): 配列内の各要素の出現数をカウントします。 PHP 関数の紹介—array_count_values(): 配列内の各要素の出現数をカウントします。 Jul 25, 2023 pm 07:18 PM

PHP 関数の紹介—array_count_values(): 配列内の各要素の出現数を数える PHP の開発では、配列内の要素を数える必要がある状況によく遭遇します。 PHP は、この目標を達成するのに役立つ便利な関数をいくつか提供しています。その 1 つが array_count_values() 関数です。 array_count_values() 関数は、配列内の各要素の出現をカウントし、連想配列を返すことができます。

Java Count はストリーム内の要素をどのようにカウントしますか? Java Count はストリーム内の要素をどのようにカウントしますか? May 11, 2023 pm 04:07 PM

注1. Countはストリーム内の要素の総数をカウントするターミナルオペレーションであり、戻り値はlong型です。 2. count() は、ストリーム内の要素の数を返します。これは帰納の特殊なケースです (帰納操作は一連の入力要素を受け取り、結合操作を繰り返し適用することでそれらを組み合わせて要約結果を作成します)。これは終末期の手術であり、結果や副作用が生じる可能性があります。端末操作の実行後、パイプは消費されたとみなされ、再利用できません。例 // リスト内に a で始まる文字列があるかどうかを確認し、最初の文字列と一致するかどうかを確認します。つまり、 truebooleananyStartsWithA=stringCollection.stream().anyMatch((s) を返します。

mysqlで個別の複数の列をカウントする問題を解決する方法 mysqlで個別の複数の列をカウントする問題を解決する方法 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;テーブル内のテスト データは次のとおりです。次に、これら 3 つの列の重複排除された列をカウントする必要があります。

PHP count() 関数を使用して配列要素の数を数える方法を学びます。 PHP count() 関数を使用して配列要素の数を数える方法を学びます。 Jun 27, 2023 am 10:37 AM

PHP は、特に配列操作において強力な開発機能を備えた非常に人気のあるサーバーサイド プログラミング言語です。 PHP の配列は、複数のデータ項目を保存および管理するために広く使用されています。配列を操作する場合、多くの場合、配列内の要素の数をカウントする必要がありますが、これは PHP の count() 関数を使用することで実現できます。 count() 関数は、配列要素の数をカウントするための PHP の組み込み関数です。この関数を使用する場合、関数のパラメータとして配列を渡すだけで済みます。

See all articles