Değişkenin dizi olup olmadığı nasıl kontrol edilir? ... veya dizi benzeri bir şey


90

foreachDeğişkenli bir döngü kullanmak istiyorum , ancak bu değişken NULLörneğin birçok farklı türde olabilir .

Yani foreachtest etmeden önce :

if(is_array($var)){
  foreach($var as ...

Ama Iteratorarayüz uygulayan bir sınıf da olabileceğini fark ettim . Belki körüm ama sınıfın arayüzü uygulayıp uygulamadığını nasıl kontrol edebilirim? is_aİşlev veya inheritsoperatör gibi bir şey var mı ? Buldum class_implements, kullanabilirim ama daha basit bir şey olabilir mi?

İkincisi, daha da önemlisi, sanırım bu işlev var, değişkenin is_arrayveya " Iteratorarabirimi uygulayıp uygulamadığını" kontrol etmek için yeterli olur mu yoksa daha fazlasını mı test etmeliyim?


2
if ($ var instanceof ArrayIterator)
Alexey

Evet, kılavuza bile bakmayan bunun işe yaramayacağından o kadar emindim ki ...
Voitcus

Yanıtlar:


80

foreachBir işlevin içinde kullanıyorsanız ve bir dizi veya Gezilebilir bir nesne bekliyorsanız, şu işlevle ipucu yazabilirsiniz:

function myFunction(array $a)
function myFunction(Traversable)

foreachBir işlevin içinde kullanmıyorsanız veya her ikisini de bekliyorsanız , değişken üzerinde yineleme yapıp yapamayacağınızı kontrol etmek için bu yapıyı kullanabilirsiniz :

if (is_array($a) or ($a instanceof Traversable))

Teşekkürler. Umarım yeterlidir ve yinelenebilecek başka dil yapıları yoktur / olmayacak.
Voitcus

is_arrayPahalı bulmuştum . Hesaplama maliyeti, dizinin boyutuyla artmış gibi görünüyordu (bu, bir dizi olup olmadığını kontrol ettiği için mantıklı değil). Ama bir kütüphanede şok edici bir şekilde başıma geldi. Bkz yorumumu bağlantılı söz konusu. Will instanceof Traversablediziler ile çalışır? Performansını test etme şansım olmadı.
ADTC

@ADTC AFAIR bir dizi çok evet'in bir örneğidir Traversable.
Ayakkabı

1
@Shoe burada denedim . İle $var = array(1,2,3);sonuçları şunlardır: is_array($var) = trueve $var instanceof Traversable = false.
ADTC

@ADTC Evet, kontrol ettim. Diziler uygulanmaz Iteratorve bu nedenle birlikte çalışmaz Traversable.
Ayakkabı

15

foreachdizileri ve nesneleri işleyebilir. Bunu şununla kontrol edebilirsiniz:

$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
    foreach ($var as ...
}

TraversableBaşkaları cevaplarında ipucu verdiği için özellikle kontrol etmenize gerek yok , çünkü tüm nesneler - tüm diziler gibi - PHP'de gezilebilir.

Daha teknik olarak:

foreachher türden geçilebilir, yani dizilerle, düz nesnelerle (erişilebilir özelliklerin geçildiği yerlerde) ve Traversablenesnelerle (veya daha çok dahili get_iteratorişleyiciyi tanımlayan nesnelerle ) çalışır.

( kaynak )

Basitçe söylemek gerekirse, yaygın PHP programlamasında, bir değişken

  • bir dizi
  • bir obje

ve değil

  • BOŞ
  • kaynak
  • skaler

foreachüzerinde kullanabilirsiniz .


5

TraversableBasit bir işlevle örneğini kontrol edebilirsiniz . Bu tüm bunlar için işe Iteratoryarar çünküIterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}

"? true: false" bölümü gereksizdir. instanceof zaten sonuç olarak bir bool değeri veriyor.
Linas

2
<?php
$var = new ArrayIterator();

var_dump(is_array($var), ($var instanceof ArrayIterator));

döner bool(false)veyabool(true)


0

Fonksiyonlar

<?php

/**
 * Is Array?
 * @param mixed $x
 * @return bool
 */
function isArray($x) : bool {
  return !isAssociative($x);
}

/**
 * Is Associative Array?
 * @param mixed $x
 * @return bool
 */
function isAssociative($x) : bool {
  if (!is_array($array)) {
    return false;
  }
  $i = count($array);
  while ($i > 0) {
    if (!isset($array[--$i])) {
      return true;
    }
  }
  return false;
}

Misal

<?php

$arr = [ 'foo', 'bar' ];
$obj = [ 'foo' => 'bar' ];

var_dump(isAssociative($arr));
# bool(false)

var_dump(isAssociative($obj));
# bool(true)

var_dump(isArray($obj));
# bool(false)

var_dump(isArray($arr));
# bool(true)

0

PHP 7.1'den beri sözde bir tür vardır iterable tam olarak bu amaç için . Tür ipucu iterable, herhangi bir diziyi ve Traversablearabirimin herhangi bir uygulamasını kabul eder . PHP 7.1 de işlevi tanıttı is_iterable(). Daha eski sürümler için, daha yeni yerleşik özellikler olmadan eşdeğer tür zorlamasını gerçekleştirmek için buradaki diğer yanıtlara bakın.

Adil oyun: BlackHole'un belirttiği gibi, bu soru yinelenebilir nesnelerin ve dizi tipi ipuçlarının bir kopyası gibi görünüyor ? ve onun cevabı benimkinden daha fazla ayrıntıya giriyor.

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.