代码之家  ›  专栏  ›  技术社区  ›  Spurious

php Iterator-如何保存所有倒数第二的元素

  •  1
  • Spurious  · 技术社区  · 11 年前

    我不知所措。我在谷歌上搜索了好几个小时,阅读了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
            )
            ...
    )
    

    感谢您的时间和帮助!

    2 回复  |  直到 11 年前
        1
  •  2
  •   Fabian Schmengler    11 年前

    它不是迭代器类的内置功能,但您仍然可以使用 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)
      }
    }
    

    DEMO

        2
  •  0
  •   Michael    11 年前

    使用 end 然后 prev 就像这样:

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