PHP ของ count () ฟังก์ชัน O (1) หรือ O (n) สำหรับอาร์เรย์หรือไม่?


98

ไม่count()จริงๆนับองค์ประกอบทั้งหมดของอาร์เรย์ PHP หรือค่านี้แคชไว้ที่ไหนสักแห่งและเพิ่งได้รับการดึง?


7
ทำไมไม่ทดสอบล่ะ มันง่ายพอที่จะทำลูปที่เพิ่มองค์ประกอบให้กับอาร์เรย์และนับทุกครั้งและกำหนดเวลา
Marc B

3
ลองดูคำถามนี้stackoverflow.com/questions/2473989/…
The Pixel Developer

คำหลักของ Google - คำถามนี้สามารถกำหนดได้เช่นกัน: PHP นับ () วนซ้ำบนอาร์เรย์หรือไม่หรือเรียกดูจากคุณสมบัติอาร์เรย์
jave.web

คำตอบ:


138

เราสามารถดูที่มา:

/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)ทำ แต่?
Matthew

1
ขอบคุณ! ฉันไม่ค่อยแน่ใจว่าฉันควรดูแหล่งที่มาหรือแหล่งที่มาที่ใด (โดยไม่ต้องตรวจสอบจากที่เก็บ)
Dexter

3
@Matt กำลังตรวจสอบว่าโครงสร้างแฮชถูกต้องหรือไม่อย่างที่ฉันเห็น กำหนดไว้ใน zend_hash.c และเป็น O (1) ด้วย
Vladislav Rastrusny

10
พลาดไม่ได้ที่จะโหวตให้กับคนที่กำลังมองหาคำตอบในซอร์สโค้ดของ PHP :)
Yasen

1
@Matt IS_CONSISTENT () เป็นเพียงการตรวจสอบความสมบูรณ์ของอาร์เรย์github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter

7

ใน PHP 5+ ความยาวจะถูกเก็บไว้ในอาร์เรย์ดังนั้นการนับจะไม่เสร็จสิ้นในแต่ละครั้ง

แก้ไข: คุณอาจพบที่น่าสนใจการวิเคราะห์นี้: ผลการดำเนินงานจำนวน PHP แม้ว่าความยาวของอาร์เรย์จะได้รับการดูแลโดยอาร์เรย์ แต่ก็ยังดูเหมือนว่าจะเร็วกว่าหากคุณจะโทรcount()หลายครั้ง


ฉันคิดว่าคุณอาจจะถูกต้องที่การเปลี่ยนแปลงนั้นเริ่มต้นด้วย PHP 5 อย่างไรก็ตามฉันยังไม่พบข้อพิสูจน์ว่า PHP 4 คือ O (n) สำหรับ count (); ฉันเพิ่งเห็นความคิดเห็นเล็ก ๆ น้อย ๆ คุณสามารถค้นหาหลักฐาน (เช่นการใช้ count () สำหรับ PHP 4) หรือไม่? ขอบคุณ
Kristopher Windsor

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โดยพื้นฐานแล้วจะให้รายละเอียดว่าการรับความยาวอาร์เรย์เป็นอย่างไร o (1) และผลกระทบของการเรียกฟังก์ชันซ้ำ
TheClair

1
การเรียกใช้ฟังก์ชันช้ากว่าการโทรออกเสมอใช่หรือไม่ ฉันไม่แปลกใจเลยที่พบว่าล่ามมีการเพิ่มประสิทธิภาพแบบอินไลน์
corsiKa

1
the count method of that object will be calledช่วยอธิบายหน่อยได้ไหม
Steel Brain

1
@SteelBrain ถ้าการดำเนินการในชั้นเรียนCountableอินเตอร์เฟซแล้วโทรเป็นสิ่งเดียวกับการโทรcount($object) $object->count()ดู3v4l.org/oYSSCเช่น
mfonda

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.