PHPのcount()関数は配列に対してO(1)またはO(n)ですか?


96

count()PHP配列のすべての要素を本当にカウントしますか、またはこの値はどこかにキャッシュされて取得されますか?


6
テストしてみませんか?配列に要素を追加して毎回カウントし、タイミングを実行するループを実行するのは簡単です。
マークB


Googleのキーワード-この質問は次のように定式化することもできます。PHPのcount()は配列を反復しますか、それとも配列のプロパティからカウントを取得しますか?
jave.web 2015

回答:


136

まあ、私たちはソースを見ることができます:

/ext/standard/array.c

PHP_FUNCTION(count)呼び出しphp_count_recursive()順番に呼び出して、zend_hash_num_elements()このように実装されている非再帰的配列、のために:

ZEND_API int zend_hash_num_elements(const HashTable *ht)
{
    IS_CONSISTENT(ht);

    return ht->nNumOfElements;
}

あなたが見ることができるので、それはだO(1)ため$mode = COUNT_NORMAL


6
IS_CONSISTENT(ht)しかし、何をしますか?
マシュー

1
ありがとう!ソース内のどこを見ればよいのか、どこからソースを取得するのか(リポジトリからチェックアウトする必要がない)がよくわかりませんでした。
デクスター

3
@Matt私が見ることができるように、それはハッシュ構造が有効かどうかをチェックしています。これはzend_hash.cで定義されており、O(1)でもあります。
Vladislav Rastrusny

10
PHPのソースコードで答えを探している誰かに投票することをお見逃しなく:)
Lamy


7

PHP 5以降では、長さは配列に格納されるため、毎回カウントされません。

編集:この分析も興味深いかもしれません:PHPカウントパフォーマンス。配列の長さは配列によって維持されますが、count()何度も呼び出す場合は、配列を保持する方が高速であるように見えます。


変更がPHP 5以降で行われたことは正しいと思いますが、PHP 4がcount()に対してO(n)であったという証拠はまだ見つかりません。私は逸話的なコメントを見るだけです。証拠を見つけることができますか(つまり、PHP 4のcount()実装)?ありがとう、
クリストファーウィンザー

3

PHPは配列のサイズを内部的に保存しますが、配列を作成するよりも遅い場合でも関数呼び出しを行っているので、ループ:

例えば、

$cnt = count($array);
for ($i =0; $i < $cnt; $i++) {
   foo($array[$i]);
}

さらに、count配列で呼び出されていることを常に確信できるとは限りません。Countableたとえば、実装するオブジェクトで呼び出されると、そのオブジェクトのcountメソッドが呼び出されます。


あなたのフォローアップとして読むことをお勧めしますjosephscott.org/archives/2010/01/php-count-performanceそれは、基本的には、配列の長さを得ることは(1)Oでどのように詳述し、繰り返し関数呼び出しの影響。
TheClair 2011

1
関数呼び出しを行うことは、それを行わないことよりも常に遅いですか?インタープリターにインライン最適化機能があるとわかっても驚かないでしょう。
corsiKa 2011

1
the count method of that object will be called、これについて少し説明してもらえますか
スチールブレイン

1
@SteelBrainは、クラスがCountableインターフェースを実装している場合、呼び出しcount($object)はの呼び出しと同じです$object->count()。たとえば、3v4l.org / oYSSCを参照してください。
mfonda 2014

you're still making a function call when which is slower than not making oneこのステートメントは間違っている可能性があります。手動トラバーサルを実行している場合、それはO(n)操作です。ただし、事前に計算された値を取得するだけの場合、操作はO(1)です。
Jamshad Ahmad
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.