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 相关文章推荐
备份mysql数据库的php代码(一个表一个文件)
May 28 PHP
php实现的一个很好用HTML解析器类可用于采集数据
Sep 23 PHP
Linux中用PHP判断程序运行状态的2个方法
May 04 PHP
浅析PHP微信支付通知的处理方式
May 25 PHP
使用array_map简单搞定PHP删除文件、删除目录
Oct 29 PHP
php随机显示指定文件夹下图片的方法
Jul 13 PHP
Zend Framework教程之Zend_Form组件实现表单提交并显示错误提示的方法
Mar 21 PHP
php格式化时间戳
Dec 17 PHP
PHP实现简单计算器小程序
Aug 28 PHP
PHP使用phpunit进行单元测试示例
Sep 23 PHP
Laravel5.5 数据库迁移:创建表与修改表示例
Oct 23 PHP
php 多继承的几种常见实现方法示例
Nov 18 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实现的仿阿里巴巴实现同类产品翻页
2009/12/11 PHP
PHP中图片等比缩放的实例
2013/03/24 PHP
JavaScript 通过模式匹配实现重载
2010/08/12 Javascript
什么是json和jsonp,jQuery json实例详详细说明
2012/12/11 Javascript
JS 实现获取打开一个界面中输入的值
2013/03/19 Javascript
JS 实现导航栏悬停效果
2013/09/23 Javascript
js获取客户端网卡的IP地址、MAC地址
2014/03/26 Javascript
《JavaScript函数式编程》读后感
2015/08/07 Javascript
基于jQuery实现点击列表加载更多效果
2016/05/31 Javascript
全面解析JavaScript中apply和call以及bind(推荐)
2016/06/15 Javascript
Ionic默认的Tabs模板使用实例
2016/08/29 Javascript
JS碰撞运动实现方法详解
2016/12/15 Javascript
javascript作用域链与执行环境详解
2017/03/25 Javascript
jquery使用iscorll实现上拉、下拉加载刷新
2017/10/26 jQuery
vue检测对象和数组的变化分析
2018/06/30 Javascript
NodeJs 文件系统操作模块fs使用方法详解
2018/11/26 NodeJs
在vue中实现给每个页面顶部设置title
2020/07/29 Javascript
详解JavaScript作用域、作用域链和闭包的用法
2020/09/03 Javascript
[49:30]DOTA2-DPC中国联赛正赛 Dragon vs Dynasty BO3 第二场 3月4日
2021/03/11 DOTA
python基础教程之元组操作使用详解
2014/03/25 Python
Django与遗留的数据库整合的方法指南
2015/07/24 Python
django 常用orm操作详解
2017/09/13 Python
Python实现的FTP通信客户端与服务器端功能示例
2018/03/28 Python
基于python的图片修复程序(实现水印去除)
2018/06/04 Python
Python Flask 搭建微信小程序后台详解
2019/05/06 Python
Python Django2.0集成Celery4.1教程
2019/11/19 Python
python:删除离群值操作(每一行为一类数据)
2020/06/08 Python
美国优质马术服装购买网站:Breeches.com
2019/12/16 全球购物
WebSphere 应用服务器都支持哪些认证
2013/12/26 面试题
TCP协议通讯的过程和步骤是什么
2015/10/18 面试题
食堂个人先进事迹
2014/01/22 职场文书
2014世界杯球队球队口号
2014/06/05 职场文书
一份没有按时交货失信于客户的检讨书
2014/09/19 职场文书
网吧管理制度范本
2015/08/05 职场文书
mysql批量新增和存储的方法实例
2021/04/07 MySQL
Springboot中如何自动转JSON输出
2022/06/16 Java/Android