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

如何使用递归数组迭代器处理多维数组?

  •  8
  • bcmcfc  · 技术社区  · 14 年前

    我正努力让这样的工作:

    function posts_formatter (&$posts){
        foreach ($posts as $k => $v){
    
            if (is_array($v)){
    
                posts_formatter($v);
    
            }else{
    
                switch (strtolower($k)){
    
                    # make email addresses lowercase
                    case (strpos($k, 'email') !== FALSE):
                        $posts[$k] = strtolower($v);
                        break;
    
                    # make postcodes uppercase
                    case (strpos($k, 'postcode') !== FALSE):
                        $posts[$k] = strtoupper($v);
                        break;
    
                    # capitalize certain things
                    case (strpos($k, 'line1') !== FALSE):
                    case (strpos($k, 'line2') !== FALSE):
                    case (strpos($k, 'line3') !== FALSE):
                    case (strpos($k, 'forename') !== FALSE):
                    case (strpos($k, 'surname') !== FALSE):
                        $posts[$k] = capitalize($v);
                        break;
                }
    
            }
        }
    }
    

    它将正确地遍历数组并格式化值,但我无法让它返回这些值。我一直在玩移除 & 在函数声明的末尾添加一个返回,但它不会做任何事情。

    另外,我想也许使用 RecursiveArrayIterator 可能是去的路。然而,尽管有一本书就在我面前,有一章是关于SPL迭代器的,但是它的例子对于实现我正在尝试的目标是毫无用处的。我该如何着手实施呢?

    编辑:

    array (
      'user' => 
      array (
        'title' => 'Mr.',
        'forename' => 'lowercase',
        'surname' => 'name',
        'businessName' => 'some dude',
        'telephone' => '07545464646',
        'postcode' => 'wa1 6nj',
        'line1' => 'blergh road',
        'line2' => 'randomLY cApitaLIzed wOrds',
        'line3' => '',
      ),
      'email' => 'CAPITALIZED@BLERGH.com',
      'address' => 
      array (
        'postcode' => 'ab1 1ba',
        'line1' => 'test road',
        'line2' => 'testville',
        'line3' => 'testshire',
      ),
      'date' => '2010-09-30'
    )
    
    1 回复  |  直到 14 年前
        1
  •  19
  •   Gordon Haim Evgi    14 年前

    好的,下面是一个很快让你发现的问题:

    $data = array(
        'title'    => 'how to work with iterators',
        'posts' => array(
            array(
            'title'  => 'introduction to iterators',
            'email'  => 'JohnDoe@example.com'
         ), array(
            'title'  => 'extending iterators',
            'email'  => 'JaneDoe@example.com'
         )
    ));
    

    主要的想法是影响 Iterator 返回 current 元素。迭代器是可堆叠的,因此应该使用 RecursiveArrayIterator 把它包装成 RecursiveIteratorIterator . 要实现自定义功能,可以将 递归迭代运算器 (如下所示)或使用其他迭代器来修饰 递归迭代运算器 :

    class PostFormatter extends RecursiveIteratorIterator
    {
        public function current()
        {
            $current = parent::current();
            switch($this->key()) {
                case 'email':
                    $current = strtolower($current);
                    break;
                case 'title':
                    $current = ucwords($current);
                    break;
                default:
                    break;
            }
            return $current;
        }
    }
    

    然后你简单地 foreach 通过迭代器

    $it = new PostFormatter(new RecursiveArrayIterator($data));
    foreach($it as $key => $post) {
        echo "$key: $post", PHP_EOL;
    }
    

    得到

    title: How To Work With Iterators
    title: Introduction To Iterators
    email: johndoe@example.com
    title: Extending Iterators
    email: janedoe@example.com
    

    您可以尝试从中获取数组 iterator_to_array iterator_apply 功能。但是,要使值重新应用于原始数组结构,不需要迭代器:

    array_walk_recursive($data, function(&$val, $key) {
        switch($key) {
            case 'title': $val = ucwords($val); break;
            case 'email': $val = strtolower($val); break;
            default: break;
        }
    });
    print_r($data);
    

    注意:使用php<5.3时,将lambda与函数名交换