Hàm count () của PHP có phải là O (1) hay O (n) dành cho mảng không?


96

count()thực sự đếm tất cả các phần tử của một mảng PHP hay giá trị này được lưu vào bộ nhớ đệm ở đâu đó và chỉ được truy xuất?


6
Tại sao không thử nghiệm nó? nó đủ đơn giản để thực hiện một vòng lặp thêm các phần tử vào một mảng và đếm mỗi lần và thực hiện một số thời gian.
Marc B


Các từ khóa của Google - câu hỏi này cũng có thể được hình thành như: PHP count () có lặp lại trên mảng hay nó lấy số đếm từ thuộc tính mảng?
jave.web

Câu trả lời:


136

Chà, chúng ta có thể xem nguồn:

/ext/standard/array.c

PHP_FUNCTION(count)các lệnh gọi php_count_recursive(), lần lượt gọi zend_hash_num_elements()mảng không đệ quy, được triển khai theo cách này:

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

    return ht->nNumOfElements;
}

Vì vậy, bạn có thể thấy, nó O(1)dành cho $mode = COUNT_NORMAL.


6
Làm gì IS_CONSISTENT(ht)mặc dù?
Matthew

1
Cảm ơn! Tôi không chắc mình nên tìm ở đâu trong nguồn hoặc lấy nguồn ở đâu (mà không cần phải kiểm tra từ kho lưu trữ).
Dexter

3
@Matt Nó đang kiểm tra xem cấu trúc băm có hợp lệ không, như tôi thấy. Nó được định nghĩa trong zend_hash.c và nó cũng là O (1).
Vladislav Rastrusny

10
Không thể bỏ lỡ để bỏ phiếu cho ai đó tìm kiếm câu trả lời trong mã nguồn của PHP :)
Lamy

1
@Matt IS_CONSISTENT () chỉ là một kiểm tra sự tỉnh táo trên mảng github.com/php/php-src/blob/PHP-5.3/Zend/zend_hash.c#L51
John Carter

7

Trong PHP 5+ độ dài được lưu trữ trong mảng nên việc đếm không được thực hiện mỗi lần.

CHỈNH SỬA: Bạn cũng có thể thấy phân tích này thú vị: Hiệu suất đếm PHP . Mặc dù độ dài của mảng được duy trì bởi mảng, nhưng có vẻ như việc giữ nó sẽ nhanh hơn nếu bạn định gọi count()nhiều lần.


Tôi nghĩ rằng bạn có thể đúng rằng thay đổi được thực hiện bắt đầu với PHP 5. Tuy nhiên, tôi vẫn chưa tìm thấy bằng chứng rằng PHP 4 là O (n) cho count (); Tôi chỉ thấy những bình luận mang tính giai thoại. Bạn có thể tìm thấy bằng chứng (tức là triển khai count () cho PHP 4) không? Cảm ơn,
Kristopher Windsor

3

PHP lưu trữ kích thước của một mảng trong nội bộ, nhưng bạn vẫn thực hiện một lệnh gọi hàm khi nó chậm hơn so với việc không tạo, vì vậy bạn sẽ muốn lưu trữ kết quả trong một biến nếu bạn đang làm điều gì đó như sử dụng nó trong vòng:

Ví dụ,

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

Ngoài ra, không phải lúc nào bạn cũng có thể chắc chắn rằng mình countđang được gọi trên một mảng. Nếu nó được gọi trên một đối tượng thực thi Countablechẳng hạn, countphương thức của đối tượng đó sẽ được gọi.


Phần tiếp theo, bạn có thể muốn đọc josephscott.org/archives/2010/01/php-count-performance Về cơ bản, nó nêu chi tiết về cách lấy độ dài mảng là o (1) và tác động của các lệnh gọi hàm lặp lại.
TheClair

1
Thực hiện một lệnh gọi hàm luôn chậm hơn so với không thực hiện một lệnh gọi? Tôi sẽ không ngạc nhiên khi thấy trình thông dịch có tối ưu hóa nội tuyến.
corsiKa

1
the count method of that object will be called, Bạn có thể vui lòng giải thích điều này một chút
Thép Brain

1
@SteelBrain nếu một lớp triển khai Countablegiao diện, thì việc gọi count($object)cũng giống như gọi $object->count(). Xem 3v4l.org/oYSSC chẳng hạn.
mfonda

you're still making a function call when which is slower than not making oneTuyên bố này có thể sai. Nếu bạn đang thực hiện chuyển tải thủ công, đó là O(n)hoạt động. Nhưng nếu bạn chỉ muốn truy xuất một giá trị được tính toán trước, thì hoạt động là O(1).
Jamshad Ahmad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.