【问题标题】:kind of iterator_to_array for a recursive iterator to get a bi-dimensional array一种用于递归迭代器的 iterator_to_array 以获得二维数组
【发布时间】:2012-02-25 02:07:39
【问题描述】:

在 PHP 中使用迭代器时,您可以使用 iterator_to_array 函数来提取迭代结果的数组。例如,假设您关注ArrayObject

$array_object = new ArrayObject(array(
   array('1', '2', '3', '4'),
   array('5', '6', '7', '8'),
   array('9', '10', '11', '12'),
));

如你所见,它的存储是一个二维数组。

我们可以创建一个FilterOperator 来只接受它的第一项(我知道使用LimitIterator 会更好,这只是一个示例目的):

class myFilterIterator extends FilterIterator
{
   public function accept()
   {
      return ($this->key() === 0);
   }
}

$filter_iterator = new myFilterIterator(new ArrayIterator($array_object));

现在,如果我这样做:

print_r(iterator_to_array($filter_iterator));

如果我手动循环遍历运算符,我会得到数组:

Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) )

但是现在如果我想使用RecursiveFilterIterator 怎么办?假设我有:

class myRecursiveFilterIterator extends RecursiveFilterIterator
{
   public function accept()
   {
      return ($this->hasChildren() || $this->key() === 0);
   }
}

$recursive_filter_iterator = new myRecursiveFilterIterator(new RecursiveArrayIterator($array_object));

如您所见,这将只接受父数组中包含的每个数组的键 0。因此,如果我对其进行递归迭代,它就会起作用:

foreach (new RecursiveIteratorIterator($recursive_filter_iterator) as $value) {
   print_r($value);
   echo '<br />';
}

结果:

1
5
9

但是,我怎样才能快速得到数组array(array(1), array(5), array(9))

如果我这样做:

print_r(iterator_to_array($recursive_filter_iterator));

print_r(iterator_to_array($recursive_filter_iterator->getInnerIterator()));

$it = new RecursiveIteratorIterator($recursive_filter_iterator);
print_r(iterator_to_array($it->getInnerIterator()));

我得到了整个原始数组:

Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) [1] => Array ( [0] => 5 [1] => 6 [2] => 7 [3] => 8 ) [2] => Array ( [0] => 9 [1] => 10 [2] => 11 [3] => 12 ) )

如果我这样做:

print_r(iterator_to_array(new RecursiveIteratorIterator($recursive_filter_iterator)));

我只得到第一项:

Array ( [0] => 9 )

如果我这样做:

print_r(iterator_to_array(new RecursiveIteratorIterator($recursive_filter_iterator->getInnerIterator())));

我得到了父数组中的最后一项,但键为 0:

Array ( [0] => 9 [1] => 10 [2] => 11 [3] => 12 ) 

我需要的是获取数组:

Array ( [0] => Array ( [0] => 1 ) [1] => Array ( [0] => 5 ) [2] => Array ( [0] => 9 ) ) 

我知道我可以让它手动循环,但我想知道是否有直接的方法,比如在iterator_to_array 中用于非递归迭代器。当然,我对 PHP 中的递归迭代器有些不理解,但它的文档在这方面真的很糟糕。

非常感谢。

【问题讨论】:

  • “它的文档真的很糟糕”——欢迎任何关于这个话题的反馈,给我发电子邮件(我在 SO 上的用户名,@php.net)。

标签: php oop iterator spl


【解决方案1】:

尚不完全清楚您真正想要做什么,但以下采用 RecursiveArrayIterator(注意:ArrayObject 不是 递归迭代器)并使用 iterator_to_array() 来获取你想要的结果数组。

class FirstOnlyRecursiveArrayIterator extends ParentIterator {
    public function __construct(RecursiveArrayIterator $it) {
         parent::__construct($it);
    }
    public function current() {
        $children = parent::current();
        return array_slice($children, 0, 1);
    }
}

$array_it = new RecursiveArrayIterator(array(
    array('1', '2', '3', '4'),
    array('5', '6', '7', '8'),
    array('9', '10', '11', '12'),
));

$filter_iterator = new RecursiveIteratorIterator(
    new FirstOnlyRecursiveArrayIterator($array_it),
    RecursiveIteratorIterator::SELF_FIRST);
print_r(iterator_to_array($filter_iterator));

【讨论】:

  • 好的,谢谢@salathe。这真的有效。但我觉得这很奇怪,或者至少我不是太了解它。 PHP 文档说 ParentIteratorFilterIterator 扩展为仅显示有子元素的元素。所以我认为它的accept() 方法只确定它的当前元素是否有子元素。必须覆盖current() 过滤方法而不是accept() 我认为它不是很干净。此外,我的示例应该可以工作,因为我也在检查 current 是否有孩子,但它没有。
【解决方案2】:

您需要/想要使用迭代器吗?您可以使用 php 的内置 array_map() 函数,该函数接受一个数组和一个函数,并将指定的函数应用于数组中的每个元素。所以你可以这样做:

<?php
function get_first($foo)
{ 
    return array_slice($foo, 0, 1); //slice the array right after the first element
}

$array_object = new ArrayObject(array(
     array('1', '2', '3', '4'),
     array('5', '6', '7', '8'),
     array('9', '10', '11', '12'),
));

$new_array = array_map("get_first", $array_object->getArrayCopy());
print_r($new_array);
?>

结果将是:

Array
(
    [0] => Array
        (
            [0] => 1
        )

    [1] => Array
        (
            [0] => 5
        )

    [2] => Array
        (
            [0] => 9
        )
)

如果我误解了您的问题,我深表歉意。

【讨论】:

  • 是的,我想实现这一点,但使用迭代器 :) 还是谢谢你,@csOlar
【解决方案3】:

好的。一种简单的方法可能是以下。它扩展了 ArrayIterator 类并覆盖 current() 函数以返回切片数组:

<?php
class FirstOnlyIterator extends ArrayIterator
{
    public function current()
    {
            $next = parent::current();
            return array_slice($next, 0, 1);
    }
}

$array_object = new ArrayObject(array(
     array('1', '2', '3', '4'),
     array('5', '6', '7', '8'),
     array('9', '10', '11', '12'),
));

$iterator = new FirstOnlyIterator($array_object);

print_r(iterator_to_array($iterator));
?>

【讨论】:

  • 嘿,是的,我知道有一些简单的方法可以实现我想要的,但我想要的是使用递归迭代器来实现。还是谢谢你。
猜你喜欢
  • 1970-01-01
  • 2013-11-11
  • 2020-03-21
  • 2014-02-17
  • 2021-12-09
  • 2023-03-09
  • 2013-09-13
  • 2014-03-27
相关资源
最近更新 更多