我很高兴PHP 7.1引入了the iterable pseudo-type。
现在虽然只是在循环这个类型的参数时很好,但是当你需要将它传递给仅接受array
或仅{{1}的PHP函数时,我不清楚该怎么做}}。例如,如果您想要执行array_diff,而Traversable
是iterable
,则会获得Traversable
。相反,如果您调用带有Iterator的函数,如果array
为iterable
,则会出错。
是否有类似array
(NOT:iterable_to_array
)和iterator_to_array
的内容?
我正在寻找一种解决方案,避免我的函数中的条件只是为了处理这种差异,而这并不依赖于我定义自己的全局函数。
使用PHP 7.1
答案 0 :(得分:7)
不确定这是你在寻找什么,但这是最简单的方法。
$array = [];
array_push ($array, ...$iterable);
我不太清楚为什么会这样。我发现你的问题很有趣,我开始摆弄PHP
完整示例:
<?php
function some_array(): iterable {
return [1, 2, 3];
}
function some_generator(): iterable {
yield 1;
yield 2;
yield 3;
}
function foo(iterable $iterable) {
$array = [];
array_push ($array, ...$iterable);
var_dump($array);
}
foo(some_array());
foo(some_generator());
如果使用函数array()
会很好,但因为它是一种语言结构有点特殊。它也不会保留关联数组中的键。
答案 1 :(得分:2)
是否有像iterable_to_array和iterable_to_traversable
这样的东西
只需将这些内容添加到您的项目中,它们就不会占用大量空间并为您提供所需的确切API。
function iterable_to_array(iterable $it): array {
if (is_array($it)) return $it;
$ret = [];
array_push($ret, ...$it);
return $ret;
}
function iterable_to_traversable(iterable $it): Traversable {
yield from $it;
}
答案 2 :(得分:1)
您可以先使用iterator_to_array
将变量转换为Traversable
:
$array = iterator_to_array((function() use ($iterable) {yield from $iterable;})());
转换方法取自this question下的评论。
这是working demo。
答案 3 :(得分:1)
术语容易混合
因此,这就是为什么如果函数A(iterable $ a){},则它接受数组的参数或 traversable 的实例(Iterator,IteratorAggregate均被接受,因为很明显这两个类都实现了 Traversable 。在我的测试中,通过ArrayIterator也是可以的)。
如果为参数指定了Iterator类型,则传入数组将导致TypeError。
答案 4 :(得分:0)
对于“可迭代数组”情况,似乎没有可以进行的单个函数调用,您要么需要在代码中使用条件函数,要么像这样定义自己的函数:
function iterable_to_array( iterable $iterable ): array {
if ( is_array( $iterable ) ) {
return $iterable;
}
return iterator_to_array( $iterable );
}
对于“ Iterable to Iterator”而言,情况要复杂得多。使用Traversable
可以很容易地将数组转换为ArrayIterator
。 Iterator
个实例可以照原样返回。剩下的Traversable
实例不是Iterator
。乍一看,您似乎可以使用IteratorIterator
来使用Traversable
。但是,给该类返回一个IteratorAggregate
的{{1}}时,该类存在错误,无法正常工作。
尽管我创建了一个包含两个转换函数的小型库,但是解决此问题的方法太长了,无法在此处发布:
答案 5 :(得分:0)
可以这样:
$array = $iterable instanceof \Traversable ? iterator_to_array($iterable) : (array)$iterable;
答案 6 :(得分:0)