如何检查变量是不是为数组?...或类似数组的东西

Posted

技术标签:

【中文标题】如何检查变量是不是为数组?...或类似数组的东西【英文标题】:How to check if variable is array?... or something array-like如何检查变量是否为数组?...或类似数组的东西 【发布时间】:2013-03-14 07:02:43 【问题描述】:

我想使用带有变量的foreach 循环,但是这个变量可以是多种不同的类型,例如NULL

所以在foreach之前我测试了一下:

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

但我意识到它也可以是一个实现Iterator接口的类。也许我是盲人但是如何检查该类是否实现了接口?有类似is_a 函数或inherits 运算符的东西吗?我找到了class_implements,我可以用,但也许有更简单的东西?

其次,更重要的是,我认为这个函数存在,足以检查变量is_array 或“实现Iterator 接口”还是我应该测试更多?

【问题讨论】:

if($var instanceof ArrayIterator) 是的,我很确定这是行不通的,甚至没有看过手册...... Iterable objects and array type hinting?的可能重复 【参考方案1】:
<?php
$var = new ArrayIterator();

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

返回bool(false)bool(true)

【讨论】:

【参考方案2】:

您可以使用一个简单的函数检查Traversable 的实例。这适用于Iterator 的所有这些,因为Iterator extends Traversable

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

【讨论】:

"? true : false" 部分是多余的。 instanceof 已经给出了一个 bool 值作为结果。【参考方案3】:

如果您在函数中使用foreach,并且您期望一个数组或Traversable 对象,您可以键入提示该函数:

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

如果您没有在函数中使用foreach,或者您希望you can simply use this construct 都检查您是否可以迭代变量:

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

【讨论】:

谢谢。我希望这已经足够了,并且没有/不会有其他可以迭代的语言结构。 我发现is_array 很贵。计算成本似乎随着数组的大小而增加(这没有任何意义,因为它只是检查它是否是一个数组)。但它在图书馆里让我震惊地发生了。请参阅链接问题中的my comment。 instanceof Traversable 可以处理数组吗?我没有机会测试它的性能。 @ADTC AFAIR 数组是Traversable 的一个实例,所以是的。 @Shoe 我试过了here。 $var = array(1,2,3); 的结果是:is_array($var) = true$var instanceof Traversable = false @ADTC 是的,刚刚检查过。数组不实现Iterator,因此不适用于Traversable【参考方案4】:

foreach 可以处理数组和对象。您可以通过以下方式检查:

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

您不需要专门检查Traversable,因为其他人在他们的答案中暗示了这一点,因为所有对象(如所有数组)都可以在 PHP 中遍历。

从技术上讲:

foreach 适用于各种可遍历对象,即数组、普通对象(遍历可访问属性的地方)和Traversable 对象(或者更确切地说是定义内部get_iterator 处理程序的对象)。

(source)

简单地说,在普通的PHP编程中,只要一个变量是

一个数组 一个对象

不是

空 资源 标量

你可以在上面使用foreach

【讨论】:

【参考方案5】:

功能

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

【讨论】:

【参考方案6】:

从 PHP 7.1 开始,就有一个伪类型 iterable 用于此目的。类型提示iterable 接受任何数组以及Traversable 接口的任何实现。 PHP 7.1 还引入了函数is_iterable()。对于旧版本,请参阅此处的其他答案,以在不使用较新的内置功能的情况下完成等效的类型强制。

公平竞争:正如 BlackHole 指出的那样,这个问题似乎与 Iterable objects and array type hinting? 重复,his or her answer 比我的更详细。

【讨论】:

【参考方案7】:

PHP 7.1.0 has introduced iterable pseudo-type and the is_iterable() function,专门为此目的设计的:

这个 […] 提出了一个新的 iterable 伪类型。这种类型类似于callable,接受多种类型而不是一种类型。

iterable 接受任何array 或实现Traversable 的对象。这两种类型都可以使用 foreach 进行迭代,并且可以在生成器中与 yield 一起使用。

function foo(iterable $iterable) 
    foreach ($iterable as $value) 
        // ...
    

这个 […] 还添加了一个函数 is_iterable(),它返回一个布尔值:true 如果一个值是可迭代的并且将被 iterable 伪类型接受,false 用于其他值。

var_dump(is_iterable([1, 2, 3])); // bool(true)
var_dump(is_iterable(new ArrayIterator([1, 2, 3]))); // bool(true)
var_dump(is_iterable((function ()  yield 1; )())); // bool(true)
var_dump(is_iterable(1)); // bool(false)
var_dump(is_iterable(new stdClass())); // bool(false)

您也可以使用函数is_array($var)来检查传递的变量是否为数组:

<?php
    var_dump( is_array(array()) ); // true
    var_dump( is_array(array(1, 2, 3)) ); // true
    var_dump( is_array($_SERVER) ); // true
?>

阅读更多How to check if a variable is an array in PHP?

【讨论】:

以上是关于如何检查变量是不是为数组?...或类似数组的东西的主要内容,如果未能解决你的问题,请参考以下文章

如何检查字符串是不是匹配数组中的正则表达式之一?

C# 检查数组是不是“满”

jQuery - 检查数组是不是为空或具有属性

检查某物是不是为数组

如何检查一个变量是不是是 JavaScript 中的一个数组?

如何检查字节数组是不是包含 Java 中的 Unicode 字符串?