PHP foreach遍历多维数组实现方式


Posted in PHP onNovember 16, 2016

介绍
正常我们的foreach可以按顺序把一维数组里面每个 key => value 打印出来,但是如果是多维数组则需要循环在嵌套循环,或则递归实现,但是这些方式都不够灵活,因为在不确定该数组是几维的情况下,不可能永无止境的嵌套循环,如果采用递归到可以解决,但是如果只想使用foreach全部循环出来该如何实现?

实现方式 一
采用PHP本身自带的迭代器类 RecursiveIteratorIterator

$test_arr = array(1,2,3,array(4,'aa'=>5,6,array(7,'bb'=>8),9,10),11,12); 
  $arrayiter = new RecursiveArrayIterator($test_arr);
  $iteriter = new RecursiveIteratorIterator($arrayiter);
  //直接打印即可按照横向顺序打印出来
  foreach ($iteriter as $key => $val){ 
    echo $key.'=>'.$val; 
  } 
  //结果
  /* 
    0=>1
    1=>2 
    2=>3
    0=>4
    aa=>5
    2=>6
    0=>7
    bb=>8
    4=>9
    5=>10
    4=>11
    5=>12
 */

实现方式 二
自己实现一个类似于 RecursiveIteratorIterator 的迭代器类,实现多维数组横向打印功能

class foreachPrintfArr implements Iterator {
    //当前数组作用域
    private $_items; 
    private $_old_items;
    //保存每次执行数组环境栈
    private $_stack = array(); 

    public function __construct($data=array()){
      $this->_items = $data;
    }

    private function _isset(){
      $val = current($this->_items);

      if (empty($this->_stack) && !$val) {
        return false;
      } else {
        return true;
      }  
    }

    public function current() {
      $this->_old_items = null;
      $val = current($this->_items);

      //如果是数组则保存当前执行环境,然后切换到新的数组执行环境
      if (is_array($val)){
        array_push($this->_stack,$this->_items);
        $this->_items = $val;
        return $this->current();
      }

      //判断当前执行完成后是否需要切回上次执行环境
      //(1) 如果存在跳出继续执行
      //(2) 如果不存在且环境栈为空,则表示当前执行到最后一个元素
      //(3) 如果当前数组环境下一个元素不存在,则保存一下当前执行数组环境 $this->_old_items = $this->_items;
      //然后切换上次执行环境 $this->_items = array_pop($this->_stack) 继续循环, 直到当前数组环境下一个
      //元素不为空为止
      while (1) {
        if (next($this->_items)) {  
          prev($this->_items); break;
        } elseif (empty($this->_stack)) {
          end($this->_items); break;
        } else {
          end($this->_items);
          if (!$this->_old_items) 
            $this->_old_items = $this->_items;
          $this->_items = array_pop($this->_stack);
        }
      }

      return $val;
    }

    public function next() {
      next($this->_items);  
    }

    public function key() {
      // 由于 key() 函数执行在 current() 函数之后
      // 所以在 current() 函数切换执行环境 , 会导致切换之前的执行环境最后一个 key
      // 变成切换之后的key , 所以 $this->_old_items 保存一下切换之前的执行环境
      // 防止key打印出错
      return $this->_old_items ? key($this->_old_items) : key($this->_items);
    }

    public function rewind() {
      reset($this->_items);
    }

    public function valid() {                                       
      return $this->_isset();
    }
  }

内部执行方式

1、foreach 循环我们自定义的foreachPrintfArr类,会自动调用内部这5个方法 valid()、rewind()、key()、next()、current() 我们只需要实现这几个方法即可.

2、调用顺序:
第1次 => rewind -> valid -> current -> key
第2次~n次 =>  next -> valid -> current -> key

$test_arr = array(1,2,3,array(4,'aa'=>5,6,array(7,'bb'=>8),9,10),11,12);
   $iteriter = new foreachPrintfArr($test_arr);
   foreach ($iteriter as $key => $val){
     echo $key.'=>'.$val;
   } 
   //结果:
   /* 
   0=>1
   1=>2
   2=>3
   0=>4
   aa=>5
   2=>6
   0=>7
   bb=>8
   4=>9
   5=>10
   4=>11
   5=>12
   */

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP开发框架总结收藏
Apr 24 PHP
Discuz Uchome ajaxpost小技巧
Jan 04 PHP
记录PHP错误日志 display_errors与log_errors的区别
Oct 09 PHP
PHP分页效率终结版(推荐)
Jul 01 PHP
PHPUnit安装及使用示例
Oct 29 PHP
php中call_user_func函数使用注意事项
Nov 21 PHP
php中session定期自动清理的方法
Nov 12 PHP
php 流程控制switch的简单实例
Jun 07 PHP
php多线程并发实现方法
Sep 30 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 PHP
php实现解析xml并生成sql语句的方法
Feb 03 PHP
LaravelS通过Swoole加速Laravel/Lumen详解
Mar 02 PHP
php数据库操作model类(使用__call方法)
Nov 16 #PHP
php实现的简单数据库操作Model类
Nov 16 #PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
Nov 16 #PHP
PHP中串行化用法示例
Nov 16 #PHP
PHP单态模式简单用法示例
Nov 16 #PHP
php实现替换手机号中间数字为*号及隐藏IP最后几位的方法
Nov 16 #PHP
php实现当前页面点击下载文件的实例代码
Nov 16 #PHP
You might like
在PHP中检查PHP文件是否有语法错误的方法
2009/12/23 PHP
php截取字符串函数substr,iconv_substr,mb_substr示例以及优劣分析
2014/06/10 PHP
几道坑人的PHP面试题 试试看看你会不会也中招
2014/08/19 PHP
WordPress开发中用于标题显示的相关函数使用解析
2016/01/07 PHP
php中文字符串截取多种方法汇总
2016/10/06 PHP
PHP应用跨时区功能的实现方法
2019/03/21 PHP
offsetParent 算法分析
2010/04/05 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
2013/08/11 Javascript
在父页面调用子页面的JS方法
2013/09/29 Javascript
jQuery使用$获取对象后检查该对象是否存在的实现方法
2016/09/04 Javascript
jQuery使用DataTable实现删除数据后重新加载功能
2017/02/27 Javascript
Web技术实现移动监测的介绍
2017/09/18 Javascript
JavaScript 2018 中即将迎来的新功能
2018/09/21 Javascript
你可能不知道的CORS跨域资源共享
2019/03/13 Javascript
js实现九宫格布局效果
2020/05/28 Javascript
Python用Pillow(PIL)进行简单的图像操作方法
2017/07/07 Python
Python实战之制作天气查询软件
2019/05/14 Python
PyQt5显示GIF图片的方法
2019/06/17 Python
python生成特定分布数的实例
2019/12/05 Python
基于python监控程序是否关闭
2020/01/14 Python
python 使用递归回溯完美解决八皇后的问题
2020/02/26 Python
Python 自由定制表格的实现示例
2020/03/20 Python
python简单实现最大似然估计&scipy库的使用详解
2020/04/15 Python
Keras预训练的ImageNet模型实现分类操作
2020/07/07 Python
css3与html5实现响应式导航菜单(导航栏)效果分享
2014/02/12 HTML / CSS
大学毕业生个人自荐信范文
2014/01/08 职场文书
和平主题的演讲稿
2014/01/12 职场文书
留学推荐信写作指南
2014/01/25 职场文书
奥巴马连任演讲稿
2014/05/15 职场文书
正风肃纪剖析材料范文
2014/10/10 职场文书
预备党员转正材料
2014/12/19 职场文书
质量保证书
2015/01/17 职场文书
幼儿园老师个人总结
2015/02/28 职场文书
台风停课通知
2015/04/24 职场文书
学校党支部公开承诺书
2015/04/30 职场文书
vue项目如何打包之项目打包优化(让打包的js文件变小)
2022/04/30 Vue.js