Як перевірити, чи є змінна масивом? ... чи щось схоже на масив


90

Я хочу використовувати foreachцикл зі змінною, але ця змінна може бути різних типів, NULLнаприклад.

Отже, перш ніж foreachперевірити:

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

Але я зрозумів, що це також може бути клас, який реалізує Iteratorінтерфейс. Можливо, я сліпий, але як перевірити, чи реалізує клас інтерфейс? Чи є щось на зразок is_aфункції або inheritsоператора? Я знайшов class_implements, я можу ним скористатися, але, можливо, є щось простіше?

А по-друге, що є більш важливим, я вважаю, що ця функція існує, було б достатньо, щоб перевірити, чи є змінна is_arrayчи "реалізує Iteratorінтерфейс", чи мені слід перевірити щось більше?


2
if ($ var instanceof ArrayIterator)
Олексій

Так, я був настільки впевнений, що це не спрацює, навіть не подивившись посібник ...
Войткус

Відповіді:


79

Якщо ви використовуєте foreachвсередині функції, і ви очікуєте масив або об'єкт, який можна пройти, ви можете ввести підказку про цю функцію за допомогою:

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

Якщо ви не використовуєте foreachвсередині функції або ви очікуєте обох, ви можете просто використати цю конструкцію, щоб перевірити, чи можна перебирати змінну:

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

Дякую. Сподіваюся, цього достатньо, і немає / не буде інших мовних конструкцій, які можна повторити.
Voitcus

Я виявив, is_arrayщо це дорого. Здавалось, обчислювальні витрати зростають із розміром масиву (що не має сенсу, оскільки це просто перевірка, чи це масив). Але це сталося зі мною приголомшливо в бібліотеці. Дивіться мій коментар у зв’язаному запитанні. Чи буде instanceof Traversableпрацювати з масивами? Я не мав можливості перевірити його ефективність.
ADTC

@ADTC AFAIR масив є екземпляром Traversableтак, так.
Взуття

1
@Shoe Я спробував тут . З $var = array(1,2,3);результатами: is_array($var) = trueі $var instanceof Traversable = false.
ADTC

@ADTC Так, просто перевірив. Масиви не реалізовуються Iteratorі, отже, не працюють з ними Traversable.
Взуття

15

foreachможе обробляти масиви та об'єкти. Ви можете перевірити це за допомогою:

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

Вам не потрібно спеціально перевіряти наявність Traversable як інші натякали на це у своїх відповідях, оскільки всі об’єкти - як і всі масиви - є прохідними в PHP.

Більш технічно:

foreachпрацює з усіма видами прохідних, тобто з масивами, з простими об'єктами (де проходять доступні властивості) та Traversableоб'єктами (а точніше об'єктами, що визначають внутрішнійget_iterator обробник).

( джерело )

Простіше кажучи, у звичайному програмуванні на PHP, коли є змінна

  • масив
  • об'єкт

і не є

  • НУЛЬ
  • ресурс
  • скаляр

Ви можете використовувати foreachна ньому.


5

Ви можете перевірити екземпляр за Traversableдопомогою простої функції. Це спрацювало б на все це, Iteratorтому щоIterator extends Traversable

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

"? true: false" частина зайва. instanceof вже дає в результаті значення bool.
Лінас,

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

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

повертає bool(false)абоbool(true)


0

Функції

<?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;
}

Приклад

<?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 існує псевдо-тип iterableсаме для цієї мети. Type-hinting iterableприймає будь-який масив, а також будь-яку реалізацію Traversableінтерфейсу. PHP 7.1 також представив цю функціюis_iterable() . Для старих версій дивіться інші відповіді тут, щоб здійснити еквівалентну реалізацію типу без нових вбудованих функцій.

Чесна гра: Як зазначив BlackHole, це питання, здається, є дублікатом підказки типу Iterable і типу масиву? і його відповідь розширюється детальніше, ніж моя.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.