¿Cómo comprobar si la variable es una matriz? ... o algo similar a una matriz


90

Quiero usar un foreachbucle con una variable, pero esta variable puede ser de muchos tipos diferentes, NULLpor ejemplo.

Entonces, antes de foreachprobarlo:

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

Pero me di cuenta de que también puede ser una clase que implemente Iteratorinterfaz. Tal vez soy ciego, pero ¿cómo verificar si la clase implementa la interfaz? ¿Existe algo como is_afunción u inheritsoperador? Lo encontré class_implements, puedo usarlo, pero ¿tal vez hay algo más simple?

Y segundo, más importante, supongo que existe esta función, ¿sería suficiente para comprobar si la variable is_arrayo "implementa la Iteratorinterfaz" o debería probar algo más?


2
if ($ var instancia de ArrayIterator)
Alexey

Sí, estaba tan seguro de que esto no funcionaría que ni siquiera había mirado el manual ...
Voitcus

Respuestas:


79

Si está utilizando foreachdentro de una función y espera una matriz o un objeto Traversable , puede escribir una pista de esa función con:

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

Si no está usando foreachdentro de una función o está esperando ambas , simplemente puede usar esta construcción para verificar si puede iterar sobre la variable:

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

Gracias. Espero que sea suficiente y que no haya / no habrá otras construcciones de lenguaje que puedan iterarse.
Voitcus

Me pareció is_arraycaro. El costo computacional pareció aumentar con el tamaño de la matriz (lo cual no tiene sentido ya que solo se trata de verificar si es una matriz). Pero me pasó espantosamente en una biblioteca. Vea mi comentario en la pregunta vinculada. ¿ instanceof TraversableFuncionará con matrices? No tuve la oportunidad de probar su rendimiento.
ADTC

@ADTC AFAIR una matriz es una instancia de Traversableentonces sí.
Zapato

1
@Zapato Lo probé aquí . Con $var = array(1,2,3);los resultados son: is_array($var) = truey $var instanceof Traversable = false.
ADTC

@ADTC Sí, recién comprobado. Las matrices no se implementan Iteratory, por lo tanto, no funcionan con Traversable.
Zapato

15

foreachpuede manejar matrices y objetos. Puedes comprobar esto con:

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

No necesita verificar específicamente, Traversableya que otros lo han insinuado en sus respuestas, porque todos los objetos, como todas las matrices, se pueden atravesar en PHP.

Más técnicamente:

foreachtrabaja con todo tipo de transitables, es decir, con matrices, con objetos planos (donde se atraviesan las propiedades accesibles) y Traversableobjetos (o más bien objetos que definen el get_iteratormanejador interno ).

( fuente )

Dicho simplemente en la programación PHP común, siempre que una variable es

  • una matriz
  • un objeto

y no es

  • NULO
  • un recurso
  • un escalar

puedes usarlo foreach.


5

Puede verificar la instancia de Traversablecon una función simple. Esto funcionaría para todo esto IteratorporqueIterator extends Traversable

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

La parte "? verdadero: falso" es redundante. instanceof ya da un valor bool como resultado.
Linas

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

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

devuelve bool(false)obool(true)


0

Funciones

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

Ejemplo

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

Desde PHP 7.1 existe un pseudo-tipo iterableexactamente para este propósito. La sugerencia de tipo iterableacepta cualquier matriz, así como cualquier implementación de la Traversableinterfaz. PHP 7.1 también introdujo la función is_iterable(). Para versiones anteriores, consulte otras respuestas aquí para lograr la aplicación de tipo equivalente sin las funciones integradas más nuevas.

Juego limpio: como señaló BlackHole, esta pregunta parece ser un duplicado de objetos Iterables y sugerencias de tipo de matriz. y su respuesta es más detallada que la mía.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.