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.MVC的模板标签系统(五)
Sep 05 PHP
我的论坛源代码(六)
Oct 09 PHP
php中常用编辑器推荐
Jan 02 PHP
全世界最小的php网页木马一枚 附PHP木马的防范方法
Oct 09 PHP
纯php打造的tab选项卡效果代码(不用js)
Dec 29 PHP
Admin generator, filters and I18n
Oct 06 PHP
基于Zend的Config机制的应用分析
May 02 PHP
php字符串按照单词进行反转的方法
Mar 14 PHP
PHP设置进度条的方法
Jul 08 PHP
php计划任务之验证是否有多个进程调用同一个job的方法
Dec 07 PHP
Yii2实现多域名跨域同步登录退出
Feb 04 PHP
Laravel 验证码认证学习记录小结
Dec 20 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
在PHP3中实现SESSION的功能(二)
2006/10/09 PHP
PHP开发过程中常用函数收藏
2009/12/14 PHP
php模拟用户自动在qq空间发表文章的方法
2015/01/07 PHP
thinkPHP显示不出验证码的原因与解决方法分析
2017/05/20 PHP
php读取出一个文件夹及其子文件夹下所有文件的方法示例
2017/06/15 PHP
JavaScript库 开发规则
2009/01/31 Javascript
JS下拉缓冲菜单示例代码
2013/08/30 Javascript
JavaScript中的Web worker多线程API研究
2014/12/06 Javascript
JS中产生标识符方式的演变
2015/06/12 Javascript
Javascript验证Visa和MasterCard信用卡号的方法
2015/07/27 Javascript
AngularJS中实现用户访问的身份认证和表单验证功能
2016/04/21 Javascript
VueJs与ReactJS和AngularJS的异同点
2016/12/12 Javascript
jQuery获取table表中的td标签(实例讲解)
2017/07/28 jQuery
原生JS实现的轮播图功能详解
2018/08/06 Javascript
使用Python读写文本文件及编写简单的文本编辑器
2016/03/11 Python
python实现杨辉三角思路
2017/07/14 Python
Python 装饰器使用详解
2017/07/29 Python
NLTK 3.2.4 环境搭建教程
2018/09/19 Python
面向对象学习之pygame坦克大战
2019/09/11 Python
pip install python 快速安装模块的教程图解
2019/10/08 Python
Python编写一个验证码图片数据标注GUI程序附源码
2019/12/09 Python
Pycharm操作Git及GitHub的步骤详解
2020/10/27 Python
python中altair可视化库实例用法
2021/01/26 Python
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
澳大利亚第一的设计师礼服租赁网站:GlamCorner
2017/08/13 全球购物
美国顶级品牌男士大码服装店:DXL
2017/08/30 全球购物
"引用"与指针的区别是什么
2016/09/07 面试题
行政主管岗位职责
2013/11/18 职场文书
早餐连锁店计划书
2014/01/08 职场文书
党员公开承诺书范文
2014/03/25 职场文书
初三开学计划书
2014/04/27 职场文书
学校党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
高三语文复习计划
2015/01/19 职场文书
2015年乡镇工作总结范文
2015/04/22 职场文书
世界上超棒的8种逻辑思维
2019/08/06 职场文书
详解Golang如何优雅的终止一个服务
2022/03/21 Golang