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 相关文章推荐
文件系统基本操作类
Nov 23 PHP
php判断字符以及字符串的包含方法属性
Aug 30 PHP
PHP文件注释标记及规范小结
Apr 01 PHP
php中如何判断一个网页请求是ajax请求还是普通请求
Aug 10 PHP
php中smarty变量修饰用法实例分析
Jun 11 PHP
PHP数组去重比较快的实现方式
Jan 19 PHP
joomla实现注册用户添加新字段的方法
May 05 PHP
完美利用Yii2微信后台开发的系列总结
Jul 18 PHP
phpstudy的php版本自由修改的方法
Oct 18 PHP
php反射学习之不用new方法实例化类操作示例
Jun 14 PHP
php输出反斜杠的实例方法
Sep 19 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
Apr 04 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 5.3.1 安装包 VC9 VC6不同版本的区别是什么
2010/07/04 PHP
深入php处理整数函数的详解
2013/06/09 PHP
CodeIgniter中使用cookie的三种方式详解
2014/07/18 PHP
php操作mongoDB实例分析
2014/12/29 PHP
Js之软键盘实现(js源码)
2007/01/30 Javascript
jQuery Ajax文件上传(php)
2009/06/16 Javascript
JavaScript生成GUID的多种算法小结
2013/08/18 Javascript
获取非最后一列td值并将title设为该值的方法
2013/10/30 Javascript
javascript + jquery实现定时修改文章标题
2014/03/19 Javascript
JavaScript的作用域和块级作用域概念理解
2014/09/21 Javascript
JS获取时间的方法
2015/01/21 Javascript
JQuery datepicker 用法详解
2015/12/25 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
关于JS变量和作用域详解
2016/07/28 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
微信小程序 图片边框解决方法
2017/01/16 Javascript
ES6中Array.includes()函数的用法
2017/09/20 Javascript
JS函数节流和函数防抖问题分析
2017/12/18 Javascript
详解node.js中的npm和webpack配置方法
2018/01/21 Javascript
react native 获取地理位置的方法示例
2018/08/28 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
ES6知识点整理之模块化的应用详解
2019/04/15 Javascript
通过图带你深入了解vue的响应式原理
2019/06/21 Javascript
uniapp开发小程序实现滑动页面控制元素的显示和隐藏效果
2020/12/10 Javascript
js定时器出现第一次延迟的原因及解决方法
2021/01/04 Javascript
[33:42]LGD vs OG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python实现的简单排列组合算法示例
2018/07/04 Python
Python完成毫秒级抢淘宝大单功能
2019/06/06 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
Python延迟绑定问题原理及解决方案
2020/08/04 Python
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
倡议书范文
2014/04/16 职场文书
赤壁观后感(2)
2015/06/15 职场文书
有关三国演义的读书笔记
2015/06/25 职场文书
《这片土地是神圣的》教学反思
2016/02/16 职场文书
调解协议书范本
2016/03/21 职场文书