Điều gì nhanh hơn và tốt hơn để xác định xem một khóa mảng có tồn tại trong PHP không?


157

Hãy xem xét 2 ví dụ này ...

$key = 'jim';

// example 1
if (isset($array[$key])) {
    // ...
}

// example 2    
if (array_key_exists($key, $array)) {
    // ...
}

Tôi muốn biết liệu một trong hai thứ này có tốt hơn không. Tôi đã luôn sử dụng cái đầu tiên, nhưng đã thấy rất nhiều người sử dụng ví dụ thứ hai trên trang web này.

Vậy, cái nào tốt hơn? Nhanh hơn? Ý định rõ ràng hơn?


Tôi đã không chạy bất kỳ điểm chuẩn, không. Tôi có nên có trước khi hỏi?
alex

4
issetsẽ không bao giờ hành xử chính xác như thế array_key_exists, ví dụ mã được cho là khiến nó hoạt động giống hệt nhau ném một Thông báo nếu khóa không tồn tại.
lừa dối

Thế còn in_array? maettig.com/1397246220
DanMan

1
@DanMan, in_arrayO(n)vì nó kiểm tra các giá trị không phải là các khóa. Chúng hầu như luôn luôn chậm hơn trừ khi bạn ncực kỳ nhỏ.
Pacerier

Tại sao không $array[$key] === null?
Pacerier

Câu trả lời:


237

isset()nhanh hơn, nhưng nó không giống như array_key_exists().

array_key_exists()hoàn toàn kiểm tra nếu khóa tồn tại, ngay cả khi giá trị là NULL.

Trong khi đó isset()sẽ trả về falsenếu khóa tồn tại và giá trị là NULL.


5
Bạn có tài nguyên cụ thể tuyên bố ngay lập tức là nhanh hơn?
Francesco Pasa

@Francesco Pasa Chỉ cần nghĩ về nó một chút. issetkhông phải là một hàm tìm kiếm mảng, nó chỉ kiểm tra sự hiện diện của một biến trong bảng ký hiệu và sẽ không lặp lại trên mảng. array_key_existsmặt khác sẽ lặp lại / tìm kiếm các khóa trong chiều thứ nhất của mảng được chỉ định.
Mưa

@Rain Tôi khá chắc chắn array_key_exists()sẽ chỉ kiểm tra xem khóa có nằm trong mảng không, điều đó có nghĩa là nó sẽ không thực hiện tìm kiếm vì đó là bảng băm.
Francesco Pasa

@FrancescoPasa Vâng, "tìm kiếm các khóa" là những gì tài liệu PHP nói. Ngoài ra, tôi không thể biết liệu "tìm kiếm" với họ có nghĩa gì đó hoàn toàn khác với ý nghĩa của nó đối với tôi.
Mưa

32

Nếu bạn quan tâm đến một số thử nghiệm tôi đã thực hiện gần đây:

https://stackoverflow.com/a/21759158/520857

Tóm lược:

| Method Name                              | Run time             | Difference
=========================================================================================
| NonExistant::noCheckingTest()            | 0.86004090309143     | +18491.315775911%
| NonExistant::emptyTest()                 | 0.0046701431274414   | +0.95346080503016%
| NonExistant::isnullTest()                | 0.88424181938171     | +19014.461681183%
| NonExistant::issetTest()                 | 0.0046260356903076   | Fastest
| NonExistant::arrayKeyExistsTest()        | 1.9001779556274      | +209.73055713%

QUAN TRỌNG: thời gian của ArrayKeyExists được phát hiện là rất sai - đó là kiểm tra giá trị không phải là khóa - theo liên kết đó cho thời gian sửa đổi trong 7.1, tốt hơn nhiều . (Cũng sẽ tốt hơn trong các phiên bản php trước, nếu Populus làm lại bài kiểm tra đó.)
ToolmakerSteve

19

Chà, sự khác biệt chính là isset()sẽ không trả về truecác khóa mảng tương ứng với một giá trị null array_key_exists().

Chạy một điểm chuẩn nhỏ cho thấy rằng isset()nó nhanh hơn nhưng nó có thể không hoàn toàn chính xác.


1
Bạn có thể chạy lại điểm chuẩn với chính xác hơn không "(isset ($ mảng [$ i]) || $ mảng [$ i] === null)"?
Tomalak

Ồ, và bạn sẽ đăng một dấu hiệu cho thấy sự khác biệt hiệu suất của hai biến thể như thế nào? Cảm ơn!
Tomalak

1
@Tomalak, tôi đã chạy ví dụ mà bạn đề xuất và thông báo rằng mảng_key_exists () nhanh hơn so vớietet () với | | nhà điều hành. codepad.org/5qyvS93x
alex

1
Từ cõi chết ... nhưng tôi cũng chạy lại điểm chuẩn và thực hiện một chỉnh sửa để vòng lặp thứ hai phải khởi tạo bộ đếm của chính nó và xóa mảng kết quả. Nó cho thấy "isset | | null" nhanh hơn. codepad.org/Np6oPvgS
KyleWpppd

3
@Tomalak, isset($array[$i]) || $array[$i] === nullkhông có ý nghĩa gì vì nó sẽ trở lại truecho mọi trường hợp. Bạn sẽ không bao giờ nhận được sai từ isset($array[$i]) || $array[$i] === nullbất kể đầu vào.
Pacerier

10

Tôi muốn thêm 2 xu của mình vào câu hỏi này, vì tôi đã bỏ lỡ một lối thoát giữa chừng.

Như đã nói isset()sẽ đánh giá giá trị của khóa để nó sẽ trả về falsenếu giá trị đó là nullnơi array_key_exists()sẽ chỉ kiểm tra xem khóa có tồn tại trong mảng không.


Tôi đã chạy một điểm chuẩn đơn giản bằng PHP 7, kết quả hiển thị là thời gian cần thiết để hoàn thành việc lặp lại:

$a = [null, true];

isset($a[0])                            # 0.3258841  - false
isset($a[1])                            # 0.28261614 - true
isset($a[2])                            # 0.26198816 - false

array_key_exists(0, $a)                 # 0.46202087 - true
array_key_exists(1, $a)                 # 0.43063688 - true
array_key_exists(2, $a)                 # 0.37593913 - false

isset($a[0]) || array_key_exists(0, $a) # 0.66342998 - true
isset($a[1]) || array_key_exists(1, $a) # 0.28389215 - true
isset($a[2]) || array_key_exists(2, $a) # 0.55677581 - false

array_key_isset(0, $a)                  # 1.17933798 - true
array_key_isset(1, $a)                  # 0.70253706 - true
array_key_isset(2, $a)                  # 1.01110005 - false

Tôi đã thêm kết quả từ chức năng tùy chỉnh này với điểm chuẩn này để hoàn thành:

function array_key_isset($k, $a){
    return isset($a[$k]) || array_key_exists($k, $a);
}

Như đã thấy và đã nói isset()là phương pháp nhanh nhất nhưng nó có thể trả về false nếu giá trị là null. Điều này có thể cho kết quả không mong muốn và thường người ta nên sử dụng array_key_exists()nếu đó là trường hợp.

Tuy nhiên, có một cách giữa và đó là sử dụng isset() || array_key_exists(). Mã này thường sử dụng hàm nhanh hơn isset()nếu chỉ isset() trả về false thì sử dụng array_key_exists()để xác thực. Hiển thị trong bảng trên, nó chỉ nhanh như gọi đơn giản isset().

Vâng, đó là một chút nữa để viết và gói nó trong một chức năng chậm hơn nhưng dễ dàng hơn nhiều. Nếu bạn cần điều này để thực hiện, kiểm tra dữ liệu lớn, v.v. hãy ghi lại đầy đủ, nếu không thì việc sử dụng 1 lần mà chi phí rất nhỏ trong chức năng array_key_isset()là không đáng kể.


7

Với Php 7 cung cấp khả năng sử dụng Toán tử kết hợp Null .

Toán tử hợp nhất null (??) đã được thêm vào dưới dạng đường cú pháp cho trường hợp phổ biến là cần sử dụng một ternary kết hợp với isset (). Nó trả về toán hạng đầu tiên của nó nếu nó tồn tại và không phải là NULL; nếu không, nó trả về toán hạng thứ hai của nó.

Vì vậy, bây giờ bạn có thể gán một giá trị mặc định trong trường hợp giá trị là null hoặc nếu khóa không tồn tại:

$var = $array[$key] ?? 'default value'

6

có một sự khác biệt từ php.net bạn sẽ đọc:

isset () không trả về TRUE cho các khóa mảng tương ứng với giá trị NULL, trong khi mảng_key_exists () thì có.

Một thử nghiệm rất không chính thức cho thấy array_key_exists()chậm hơn khoảng 2,5 lần so vớiisset()


3

Kết hợp isset()is_null()cung cấp cho hiệu suất tốt nhất chống lại các chức năng khác như: array_key_exists(), isset(), isset()+ array_key_exists(), is_null(), isset()+ is_null(), vấn đề duy nhất ở đây là chức năng sẽ không chỉ trả lại false nếu chìa khóa không tồn tại, nhưng ngay cả những tồn tại quan trọng và có giá trị null.

Kịch bản điểm chuẩn:

<?php
  $a = array('a' => 4, 'e' => null)

  $s = microtime(true); 
  for($i=0; $i<=100000; $i++) { 
    $t = (isset($a['a'])) && (is_null($a['a'])); //true 
    $t = (isset($a['f'])) && (is_null($a['f'])); //false
    $t = (isset($a['e'])) && (is_null($a['e']));; //false 
  } 

  $e = microtime(true); 
  echo 'isset() + is_null() : ' , ($e-$s)."<br><br>";
?>

Tín dụng : http://www.zomeoff.com/php-fast-way-to-determine-a-key-elements-existance-in-an-array/


1

Như "nhanh hơn": Hãy thử nó (tiền của tôi vẫn còn array_key_exists(), nhưng tôi không thể thử ngay bây giờ).

Như "rõ ràng hơn trong ý định": array_key_exists()


3
isset () thực sự nhanh hơn đáng kể nếu bạn không quan tâm đến hành vi null (xem randombenchmark.com/?p=29 ).
Matt Kantor

0

Rõ ràng ví dụ thứ hai rõ ràng hơn trong ý định, không có câu hỏi nào về nó. Để tìm ra ví dụ # 1 làm gì, bạn cần phải làm quen với các đặc điểm khởi tạo biến của PHP - và sau đó bạn sẽ thấy rằng nó hoạt động khác với các giá trị null, v.v.

Để nhanh hơn - tôi không có ý định suy đoán - hãy chạy trong một vòng lặp chặt chẽ vài trăm nghìn lần trên phiên bản PHP của bạn và bạn sẽ tìm ra :)


-2

Mã của bạn isset($array[$i]) || $array[$i] === null, sẽ trả về true trong mọi trường hợp, ngay cả khi khóa không tồn tại (và mang lại thông báo chỉ mục không xác định). Để có hiệu suất tốt nhất những gì bạn muốn làif (isset($array[$key]) || array_key_exists($key,$array)){doWhatIWant();}


1
Thời gian duy nhất $array[$i] === nullsẽ được thực thi là khi $ i tồn tại trong mảng và có giá trị NULL ..
Niclas Larsson
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.