php迭代器-如何保存倒数第二的元素


php Iterator - how to save all second to last elements

我不知道。我在谷歌上搜索,在这里搜索,阅读php手册几个小时,但我不能想出一个解决方案。

我得到了以下数组结构:

[x] => Array
    (
        ...
                  [object_name_1] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )
                  ...
                  [object_name_4] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )
                  ...
                  [object_name_n] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )
...
[y] => Array
    (
        ...
        [object_group_xyz] => Array
           (
                  [object_name_a] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )
                  ...
           )
                  ...
                  [object_name_e] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )
                  ...
                  [object_name_z] => Array
                      (
                          [db] => x
                          [form] => y
                          [value] => z
                      )

现在我的问题是:我想保存所有object_name_x数组。数组的深度是未知的,事实上,不同的object_name_n对象的深度可以依赖于同一个数组。但他们永远是最后一片叶子。

我怎样才能解决这个问题?据我所知,RecursiveIteratorIterator不可能只考虑倒数第二个对象。

我的输出应该是这样的:

Array
(
    [object_name_1] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
    [object_name_4] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
    [object_name_n] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
    [object_name_a] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
    [object_name_e] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
    [object_name_z] => Array
        (
            [db] => x
            [form] => y
            [value] => z
        )
        ...
)

感谢您的时间和帮助!

这不是迭代器类的内置功能,但您仍然可以使用RecursiveIteratorIterator并构建堆栈,以便在到达叶节点时可以后退一步。

下面是一个PoC,它不是一个超级干净的解决方案,但它是有效的,应该展示原则:

class MyIterator extends RecursiveIteratorIterator {
  protected $stack = array();
  protected $result = array();
  public function __construct($data)
  {
    parent::__construct(new RecursiveArrayIterator($data), RecursiveIteratorIterator::SELF_FIRST);
  }
  public function getObjects()
  {
    foreach($this as $dummy);
    return $this->result;
  }
  public function rewind()
  {
    parent::rewind();
    $this->stack = array();
    $this->result = array();
    $this->pushIfNoLeaf();
  }
  public function next()
  {
    parent::next();
    $this->pushIfNoLeaf();
  }
  public function beginIteration()
  {
    parent::beginIteration();
    $this->popIfLeaf();
  }
  public function beginChildren()
  {
    parent::beginChildren();
    $this->popIfLeaf();
  }
  protected function pushIfNoLeaf()
  {
    if ($this->getSubIterator()->hasChildren()) {
      $this->stack[] = array('key' => $this->key(), 'value' => $this->current());
    }
  }
  protected function popIfLeaf()
  {
    if (!$this->getSubIterator()->hasChildren()) {
      $item = array_pop($this->stack);
      $this->result[$item['key']] = $item['value'];
    }
  }
}
$data = array(
'obj1' => array(1,2,3),
'arr1' => array(
  'obj2' => array(4,5,6),
  'obj3' => array(7,8,9)
)
);
$iterator = new MyIterator($data);
var_dump($iterator->getObjects());

示例输出

array(3) {
  ["obj1"]=>
  array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
  }
  ["obj2"]=>
  array(3) {
    [0]=>
    int(4)
    [1]=>
    int(5)
    [2]=>
    int(6)
  }
  ["obj3"]=>
  array(3) {
    [0]=>
    int(7)
    [1]=>
    int(8)
    [2]=>
    int(9)
  }
}

像这样使用endprev:

$array = array('one' => 1, 'two' => 2, 'three' => 3);
end($array);
echo prev($array); // Ouputs 2
echo key($array); // Ouputs 'two'

在你的例子中,你应该有:

$array = array(
  0 => array(
    0 => (object) array('name' => 'a'),
    1 => (object) array('name' => 'b'),
    2 => (object) array('name' => 'c'),
  ),
  1 => array(
    3 => (object) array('name' => 'd'),
    4 => (object) array('name' => 'e'),
    5 => (object) array('name' => 'f'),
  ),
);
$objects = array();
foreach ($array as $a)
{
  end($a);
  $prev = prev($a);
  $objects[key($a)] = $prev;
}
echo '<pre>' . print_r($objects, TRUE) . '</pre>';

输出:

Array
(
    [1] => stdClass Object
        (
            [name] => b
        )
    [4] => stdClass Object
        (
            [name] => e
        )
)