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&&mysql)四
Oct 09 PHP
php之字符串变相相减的代码
Mar 19 PHP
Php注入点构造代码
Jun 14 PHP
利用PHP实现智能文件类型检测的实现代码
Aug 02 PHP
PHP curl 并发最佳实践代码分享
Sep 05 PHP
php自定义urlencode,urldecode函数实例
Mar 24 PHP
PHP实现在线阅读PDF文件的方法
Jun 17 PHP
php实现网页缓存的工具类分享
Jul 14 PHP
php_pdo 预处理语句详解
Nov 21 PHP
PHP实现对xml的增删改查操作案例分析
May 19 PHP
PHP调用全国天气预报数据接口查询天气示例
Feb 20 PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
Aug 13 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在项目中寻找代码的坏味道(综艺命名)
2012/07/19 PHP
浅析十款PHP开发框架的对比
2013/07/05 PHP
php把session写入数据库示例
2014/02/26 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
2017/05/09 PHP
thinkPHP5框架自定义验证器实现方法分析
2018/06/11 PHP
js tab效果的实现代码
2009/12/26 Javascript
JavaScript原型继承之基础机制分析
2011/08/26 Javascript
js实现广告漂浮效果的小例子
2013/07/02 Javascript
JS中获取数据库中的值的方法
2013/07/14 Javascript
js 遍历json返回的map内容示例代码
2013/10/29 Javascript
jquery 操作iframe的几种方法总结
2013/12/13 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
使用JQuery库提供的扩展功能实现自定义方法
2014/09/09 Javascript
浅析JavaScript动画
2015/06/10 Javascript
Web前端开发工具——bower依赖包管理工具
2016/03/29 Javascript
JavaScript检测原始值、引用值、属性
2016/06/20 Javascript
集成vue到jquery/bootstrap项目的方法
2018/02/10 jQuery
使用vue-cli创建项目的图文教程(新手入门篇)
2018/05/02 Javascript
微信小程序Echarts覆盖正常组件问题解决
2019/07/13 Javascript
在layui tab控件中载入外部html页面的方法
2019/09/04 Javascript
layui问题之模拟table表格中的选中按钮选中事件的方法
2019/09/20 Javascript
浅谈webpack构建工具配置和常用插件总结
2020/05/11 Javascript
python使用opencv进行人脸识别
2017/04/07 Python
python微信跳一跳系列之棋子定位像素遍历
2018/02/26 Python
matplotlib 多个图像共用一个colorbar的实现示例
2020/09/10 Python
英国手机壳购买网站:Case Hut
2019/04/11 全球购物
巴西最大的珠宝连锁店:Vivara
2019/04/18 全球购物
TCP/IP模型的分界线
2012/12/01 面试题
Java基础知识面试题
2014/03/25 面试题
店长助理岗位职责
2013/12/13 职场文书
五十岁生日宴会答谢词
2014/01/15 职场文书
节能环保演讲稿
2014/08/28 职场文书
关于安全的广播稿
2014/10/23 职场文书
医院志愿者活动总结
2015/05/06 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
Win11应用商店打开闪退怎么解决? win11应用商店打不开的多种解决办法
2022/04/05 数码科技