Boş dizileri kontrol etme: boşa karşı sayma


99

' Bir PHP dizisinin boş olup olmadığı nasıl anlaşılır ' sorusu bu soruyu düşünmemi sağladı

Bir dizinin boş olup olmadığını belirlemek countyerine kullanılması gereken bir sebep var mı empty?

Benim kişisel düşüncem, 2'nin boş diziler durumunda eşdeğer olması, emptyçünkü bir boolean soruya boole cevabı veriyor olmasıydı. Yukarıda bağlantısı verilen sorudan count($var) == 0, popüler yöntem bu gibi görünüyor . Bana göre teknik olarak doğru olsa da hiçbir anlam ifade etmiyor. Örneğin S: $ var, boş musunuz? C: 7 . Hmmm ...

count == 0Bunun yerine kullanmam gereken bir sebep mi yoksa sadece kişisel bir zevk meselesi mi var?

Şimdi silinmiş bir cevap için yorumlarda başkaları tarafından belirtildiği gibi, counttüm öğeleri sayması gerekeceğinden, büyük diziler için performans etkileri olacaktır, oysa emptyboş olmadığını anladığı anda durabilir. Öyleyse, bu durumda aynı sonuçları veriyorlarsa, ancak countpotansiyel olarak verimsizse, neden kullanalım count($var) == 0?


Niyetinizin konuşmayı yalnızca dizilerle sınırlamak olduğunu varsayıyorum, ancak nesnelerle (örneğin Sayılabilir, Yineleyici, vb. Uygulayanlar) çalışıyorsanız oyunun tamamen değiştiğini belirtmekte fayda var.

9
Boş bir dizi falsePHP'de eşittir - empty()veya gerekmez count().
Cobby

@Kobi Kodu lütfen.
TheRealChx101

@ TheRealChx101 Olduğu gibi, şunu yapın: if (!$myArray) { echo "array is empty"; } sandbox.onlinephpfunctions.com/code/…
Cobby

Günümüzde bağlantılı sorudaki popüler seçenek kullanmaktır empty().
PhoneixS

Yanıtlar:


99

Genelde kullanırım empty. İnsanların sayımı neden gerçekten kullandıklarından emin değilim - Dizi büyükse sayı daha uzun sürer / daha fazla ek yüke neden olur. Dizinin boş olup olmadığını bilmeniz gerekiyorsa, boş kullanın.


4
Bu işlevler, dizi boş olmadığında gerçekten farklılık gösterir .
Jacco

2
@Jacco: Buna itiraz etmiyorum. Ancak, boş olduğunu test ediyorsanız, bunun ne kadar alaka düzeyine sahip olduğunu görmüyorum - bu, işlevin geri döneceği bir boole sonucu olan bir soru. Neyin boş kabul edildiğine gelince, test ettiğiniz değişken tamamen farklı bir konu olan bir dizi olmadığı sürece, bu kriterlerin nasıl yanlış cevap vereceğini görmeyin.
prodigitalson

23
@prodigitalson O(1)PHP öğelerin sayısını dahili olarak sakladığından, sayının olduğunu söyleyebilirim . Bu cevaba göz atın stackoverflow.com/a/5835419/592454
elitalon

4
@eliton: ama yine de - performansta hiç veya çok az fark olsa bile, sayıma ihtiyacınız yoksa neden kullanılsın?
prodigitalson

4
empty () hataları çok bağışlayıcıdır. Üst sınıfının özel bir üye değişkeninde boş () test edilmiş bir alt sınıfın hata ayıklaması için 2 saat harcadım (süper sınıfın üye değişkeninin kapsamı korunmalıdır, ancak boş () hiçbir hata döndürmedi - sonuç basitçe olması gereken bir şeydi oldu, olmadı: alt sınıftaki üye değişkenin yokluğu, bu üye değişkeni, bir dizi boşmuş gibi, tam olarak aynı şekilde ele alındı ​​- yani, hiç elemanı yokmuş gibi. Bu sorunlu ve PHP'nin çok bağışlayıcı olduğu başka bir örnek.
Matthew Slyman

47

Hangisinin gerçekten daha hızlı olduğunu merak ediyordum, bu yüzden bu işlevleri karşılaştırmak için basit bir komut dosyası hazırladım.

<?php

function benchmark($name, $iterations, $action){
    $time=microtime(true);
    for($i=0;$i<=$iterations;++$i){
        $action();
    }
    echo $name . ' ' . round(microtime(true)-$time, 6) . "\n";
}

$iterations = 1000000;
$x = array();
$y = range(0, 10000000);
$actions = array(
    "Empty empty()" => function() use($x){
        empty($x);
    },
    "Empty count()" => function() use($x){
        count($x);
    },
    "Full empty()" => function() use($y){
        empty($y);
    },
    "Full count()" => function() use($y){
        count($y);
    },
    ############
    "IF empty empty()" => function() use($x){
        if(empty($x)){ $t=1; }
    },
    "IF empty count()" => function() use($x){
        if(count($x)){ $t=1; }
    },
    "IF full empty()" => function() use($y){
        if(empty($y)){ $t=1; }
    },
    "IF full count()" => function() use($y){
        if(count($y)){ $t=1; }
    },
    ############
    "OR empty empty()" => function() use($x){
        empty($x) OR $t=1;
    },
    "OR empty count()" => function() use($x){
        count($x) OR $t=1;
    },
    "OR full empty()" => function() use($y){
        empty($y) OR $t=1;
    },
    "OR full count()" => function() use($y){
        count($y) OR $t=1;
    },
    ############
    "IF/ELSE empty empty()" => function() use($x){
        if(empty($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE empty count()" => function() use($x){
        if(count($x)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full empty()" => function() use($y){
        if(empty($y)){ $t=1; } else { $t=2; }
    },
    "IF/ELSE full count()" => function() use($y){
        if(count($y)){ $t=1; } else { $t=2; }
    },
    ############
    "( ? : ) empty empty()" => function() use($x){
        $t = (empty($x) ? 1 : 2);
    },
    "( ? : ) empty count()" => function() use($x){
        $t = (count($x) ? 1 : 2);
    },
    "( ? : ) full empty()" => function() use($y){
        $t = (empty($y) ? 1 : 2);
    },
    "( ? : ) full count()" => function() use($y){
        $t = (count($y) ? 1 : 2);
    }
);

foreach($actions as $name => $action){
    benchmark($name, $iterations, $action);
}
//END

Bunu yaptığım için normalde count () / empty () ile ilişkilendirilecek işlemleri yapan performansı da kontrol etmeye çalıştım.

PHP 5.4.39 kullanımı:

Empty empty() 0.118691
Empty count() 0.218974
Full empty() 0.133747
Full count() 0.216424
IF empty empty() 0.166474
IF empty count() 0.235922
IF full empty() 0.120642
IF full count() 0.248273
OR empty empty() 0.123875
OR empty count() 0.258665
OR full empty() 0.157839
OR full count() 0.224869
IF/ELSE empty empty() 0.167004
IF/ELSE empty count() 0.263351
IF/ELSE full empty() 0.145794
IF/ELSE full count() 0.248425
( ? : ) empty empty() 0.169487
( ? : ) empty count() 0.265701
( ? : ) full empty() 0.149847
( ? : ) full count() 0.252891

HipHop VM 3.6.1'i (dbg) kullanma

Empty empty() 0.210652
Empty count() 0.212123
Full empty() 0.206016
Full count() 0.204722
IF empty empty() 0.227852
IF empty count() 0.219821
IF full empty() 0.220823
IF full count() 0.221397
OR empty empty() 0.218813
OR empty count() 0.220105
OR full empty() 0.229118
OR full count() 0.221787
IF/ELSE empty empty() 0.221499
IF/ELSE empty count() 0.221274
IF/ELSE full empty() 0.221879
IF/ELSE full count() 0.228737
( ? : ) empty empty() 0.224143
( ? : ) empty count() 0.222459
( ? : ) full empty() 0.221606
( ? : ) full count() 0.231288

PHP kullanıyorsanız sonuçlar:

  1. empty (), her iki senaryoda da count () 'dan çok daha hızlıdır, boş ve doldurulmuş bir dizi ile

  2. count () aynı şeyi dolu veya boş bir dizide gerçekleştirir.

  3. Basit bir EĞER yapmak veya sadece bir Boole işlemi yapmak aynıdır.

  4. EĞER / ELSE (?:] 'Den çok az daha etkilidir. Ortada ifadelerle milyarlarca yineleme yapmıyorsanız, bu tamamen önemsizdir.

HHVM kullanıyorsanız sonuçlar:

  1. empty (), count () 'dan biraz daha hızlı ama önemsiz bir şekilde.

    [Geri kalanı PHP'deki ile aynıdır]

Sonuç olarak, dizinin boş olup olmadığını bilmeniz gerekiyorsa, her zaman boş () kullanın;

Bu, pek çok şeyi hesaba katmadan yapılan ilginç bir testti. Bu sadece bir kavram kanıtıdır ve üretimdeki işlemleri yansıtmayabilir.


Örnek test kodu için teşekkürler .... Sadece kullandım ve if($x){daha hızlı olduğunu buldum if(empty($x)){(yalnızca $xbeyan edildiğini biliyorsanız çalışır ).
Redzarf

Test kodunuz gerçekten kötü. Anonim işlev çağrısı gibi birçok ek şey ekliyorsunuz. Kaldırırsam ve çıplak kodu çalıştırırsam (birbiri ardına döngü için) o zaman büyük bir fark elde ederim. Demek istediğim, bu durumda if ifadesinde hayır countve emptyçağrı yoksa daha hızlıdır . Sonra gelir emptyve sürer count. Ancak çıplak durumda sizinkiyle karşılaştırıldığında, boş on kat daha hızlıdır! Basit dizi testi: 0.104662, boş: 0.177659, sayı: 1.175125 PHP 5.6 üzerinde aksi halde kodunuz bu sürümde de belirttiğiniz gibi aynı sonucu verir. Sadece sahte sonuçlar.
golddragon007

16

Bence bu sadece kişisel bir tercih. Bazıları emptydaha hızlı olduğunu söyleyebilir (örneğin, http://jamessocol.com/projects/count_vs_empty.php ), diğerleri countise aslında diziler için yapıldığından daha iyi olduğunu söyleyebilir . emptydaha geneldir ve diğer türlere uygulanabilir.

php.net countbununla birlikte şu uyarıyı verir :

count (), ayarlanmamış bir değişken için 0 döndürebilir, ancak boş bir diziyle başlatılmış bir değişken için de 0 döndürebilir. Bir değişkenin ayarlanıp ayarlanmadığını test etmek için isset () kullanın.

Diğer bir deyişle, değişken atanmamışsa, PHP'den tanımsız olduğunu belirten bir uyarı alırsınız. Bu nedenle, kullanmadan önce countdeğişkeni ile kontrol etmek tercih edilir isset. Bu gerekli değildir empty.


3
İlginçtir ki, lehine olan bir argüman count, başlangıçta diziler için yapılmış olması ... yine de nesneler uygulayabilir Countableve skaler değerleri iletebilir count()ve geçerli bir sonuç elde edebilirsiniz.

1
saymak () olabilir ayarlanmamış bir değişken için 0 döndürebilir, ancak olabilir de ... . Belirsizliğini ifade etmek için modal fiiller kullanan resmi belgeler: p
nawfal

Konuyla ilgili sadece bir yorum isset(). PHP'deki bildirimler konusunda endişeleniyorsanız, dizinizi önceden bildirmiş olmalısınız. PHP'nin dizinizi dinamik olarak bildirmesine izin verirseniz, o noktada da bir uyarı alırsınız. Bence php.net'teki uyarının asıl amacı, countboş bir dizinin vereceği sonucu verdiği için bir dizinin bildirilip bildirilmediğini belirlemek için kullanmamanız gerektiğidir .
Noah Duncan

12

Bir dizinin boş olup olmadığını belirlerken sayımın boş yerine kullanılmasının bir nedeni var mı?

Boş olmayan dizi üzerinde boyutunu bilerek bir şey yapmanız gerektiğinde:

if( 0 < ( $cnt = count($array) ) )
{
 echo "Your array size is: $cnt";
}
else
 echo "Too bad, your array is empty :(";

Ama saydığın şeyin bir dizi olduğundan% 100 emin olmadıkça count kullanmanızı tavsiye etmem. Son zamanlarda kodda hata ayıklama yapıyordum, burada FALSEboş dizi yerine hata işlevi dönüyordu ve keşfettiğim şey şuydu:

var_dump(count(FALSE));

çıktı:

int 1

O zamandan beri kullanıyorum emptyya if(array() === $array)emin sahip olduğum olmaya dizi boştur.


6

count()uygulayan dizi benzeri arabirimlerle daha iyi çalışıyor gibi görünüyor ArrayAccess/Countable. empty()Bu tür nesneler için öğeleri olmasa bile true değerini döndürür. Tipik olarak bu sınıflar Countablearabirimi uygular , bu nedenle soru "Bu koleksiyon öğeler içeriyor mu?" uygulama hakkında bir varsayımda bulunmadan count()daha iyi bir seçenektir.


" Bu tür nesneler için öğeleri olmasa bile yanlışempty döndürür " mü demek istiyorsun ?
alexw

Evet. Bir sınıfın "boş" olup olmadığını tanımlamasına izin verecek bir arayüz yoktur. Ve bir tane olması gerçekten mantıklı değil.
Ryan

+1 Kullanmak count, kodunuzun "ortak" bir yöntem uygulanmış bir koleksiyonu kabul etmesi mantıklıysa, daha esnek ve genişletilebilir bir çözüm olacaktır… IMO bu, kullanıp kullanmadığınızı countveya başka şekillerde tanımlamak için tek uygun kriter olabilir ...
ClemC

count()7.2'nin büyük dezavantajı, artık boş değişkenleri alamamasıdır.
Ryan

5

Alternatif olarak, değişkeni bir boole olarak çevirebilirsiniz (örtük veya açık olarak):

if( $value )
{
  // array is not empty
}

if( (bool) $value )
{
  // array is still not empty
}

Bu yöntem E_NOTICE, değişken tanımlanmamışsa benzer şekilde bir oluşturur count().

Daha fazla bilgi için, tür karşılaştırmaları hakkındaki PHP Kılavuzu sayfasına bakın .


1
Bu, kontrol etmenin en iyi yoludur, yalnızca empty()açıkça bir E_NOTICE (bu genellikle kötü bir fikirdir, IMO) tetiklemekten kaçınmaya çalışıyorsanız kullanın. Açıkça boş kullanmak hatalı kodlara yol açacaktır.
Cobby

3

Kişisel tercihim daha çok zarafeti kodlamaktır (özel kullanım durumuma göre). Dan McG ile aynı fikirdeyim, çünkü count () söz konusu test için doğru veri türüyle (bu durumda boole) yanıt vermiyor ve geliştiriciyi bir 'if' ifadesini doldurmak için daha fazla kod yazmaya zorluyor.

Bunun performans üzerinde önemli bir etkisinin olup olmadığı, yalnızca çok büyük diziler için tartışmalıdır (muhtemelen çoğu kurulumda zaten yeterli bellek ayırmaya sahip olmayacaksınız).

Özellikle PHP'nin $ _POST dizisi söz konusu olduğunda, bana göre şunu yazmak / görmek çok daha "mantıklı" görünüyor:

if ( !empty ( $_POST ) ) {
    // deal with postdata
}

3

Umarım bu, daha önce yanıtlanmış (ve biraz tartışılmış) olmasına rağmen birine yardımcı olabilir. Kendi senaryomda, tüm dizilerimin 7 öğeye sahip olduğunu biliyorum (kontroller kodumda daha önce yapılmıştır) ve array_diffelbette eşit olduğunda sıfır dizisi döndüren bir gerçekleştiriyorum .

34 saniye count17 saniye vardı empty. Her ikisi de bana aynı hesaplamaları veriyor, böylece kodum hala iyi.

Bununla birlikte , PHP'deki gibi ==veya deneyebilirsiniz - İki dizinin eşit olup olmadığını kontrol edin . Söyleyebileceğim en iyi şey, try vs vs , sonra hangisinin kendi en iyi performansınızı verdiğini görün. Benim durumumda en yavaş olanıydı, bu yüzden şimdi kullanıyorum ... bir sonraki kontrol edeceğim===countempty== empty arraycountemptyserialize


2

Tercih herhangi bir neden yoktur count($myArray) == 0üzerinde empty($myArray). Aynı anlamlara sahipler. Bazıları birini diğerinden daha okunaklı bulabilir. Biri diğerinden marjinal olarak daha iyi performans gösterebilir, ancak php uygulamalarının büyük çoğunluğunda önemli bir faktör olması muhtemel değildir. Tüm pratik amaçlar için, seçim bir zevk meselesidir.


1
Ya "performans" olayı? "Pratik amaçlar" açıklamasını kullanmak kötü alışkanlıklara yol açar. Sayıma countihtiyacınız olduğunda kullanın , emptykoleksiyonun boş olup olmadığını kontrol etmeniz gerektiğinde kullanın. Elbette dizeler veya boş değerler gibi uç durumlar vardır, ancak programcının kodu hakkında düşünmesi gerekir. Kabul etmeyebilirsin, buna iznin var.
Namek

bazı zamanlar, count ($ myArray) ile, $ myArray FALSE değeri gibi bir booleen ise, sayım çalışmıyor (php5.3 üzerinde test edildi).
Mimouni

1

Bazen boş kullanmak bir zorunluluktur. Örneğin bu kod:

$myarray = array();

echo "myarray:"; var_dump($myarray); echo "<br>";
echo "case1 count: ".count($myarray)."<br>";
echo "case1 empty: ".empty($myarray)."<br>";

$glob = glob('sdfsdfdsf.txt');

echo "glob:"; var_dump($glob); echo "<br>";
echo "case2 count: ".count($glob)."<br>";
echo "case2 empty: ".empty($glob);

Bu kodu şu şekilde çalıştırırsanız: http://phpfiddle.org/main/code/g9x-uwi

Bu çıktıyı alırsınız:

myarray:array(0) { } 
case1 count: 0
case1 empty: 1

glob:bool(false) 
case2 count: 1
case2 empty: 1

Yani countboş glob çıktısı alırsanız, yanlış çıktı alırsınız. Boşluğu kontrol etmelisiniz.

Gönderen glob belgelerinde:

Eşleşen dosyaları / dizinleri içeren bir dizi, eşleşmeyen dosya yoksa boş bir dizi veya hata durumunda FALSE döndürür.
Not: Bazı sistemlerde boş eşleşme ile hatayı ayırt etmek imkansızdır.

Ayrıca şu soruyu kontrol edin: Count (false) neden 1 döndürür?


1

Negatif olarak ayrıştırılan bir değişken int(1)ile geri döneceği içincount()

($array === [] || !$array)Boş bir diziyi test etmeyi tercih ederim .

Evet, boş bir dizi beklemeliyiz, ancak zorunlu dönüş türleri olmadan işlevler üzerinde iyi bir uygulama beklememeliyiz.

İle örnekler count()

var_dump(count(0));
> int(1)
var_dump(count(false));
> int(1)

0

Aklımı yeniden yarattım çocuklar, teşekkürler.

Tamam, kullanımı arasında hiçbir fark yoktur emptyve count. Teknik olarak, countdiziler emptyiçin kullanılmalı ve diziler kadar diziler için de kullanılabilir. Yani çoğu durumda, onlar birbirleriyle değiştirilebilir ve php docs görürseniz, öneri listesini göreceksiniz countsen iseler emptyve tersi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.