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+Ajax异步通讯实现用户名邮箱验证是否已注册( 2种方法实现)
Dec 28 PHP
php仿QQ验证码的实例分析
Jul 01 PHP
php更新修改excel中的内容实例代码
Feb 26 PHP
PHP微框架Dispatch简介
Jun 12 PHP
destoon整合ucenter后注册页面不跳转的解决方法
Jun 21 PHP
Yii实现自动加载类地图的方法
Apr 01 PHP
PHP实践教程之过滤、验证、转义与密码详解
Jul 24 PHP
PHP实现的折半查询算法示例
Oct 09 PHP
PHP实现字符串翻转功能的方法【递归与循环算法】
Nov 03 PHP
PHP给源代码加密的几种方法汇总(推荐)
Feb 06 PHP
浅析php如何实现爬取数据原理
Sep 27 PHP
laravel 模型查询按照whereIn排序的示例
Oct 16 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通过iconv将字符串从GBK转换为UTF8字符集
2011/07/18 PHP
一个经典实用的PHP图像处理类分享
2014/11/18 PHP
LaravelS通过Swoole加速Laravel/Lumen详解
2018/03/02 PHP
jQuery 浮动广告实现代码
2008/12/25 Javascript
30个最佳jQuery Lightbox效果插件分享
2011/04/11 Javascript
JSON 数字排序多字段排序介绍
2013/09/18 Javascript
获得Javascript对象属性个数的示例代码
2013/11/21 Javascript
jQuery热气球动画半透明背景的后台登录界面代码分享
2015/08/28 Javascript
jquery实现左右无缝轮播图
2020/07/31 Javascript
ES6中Math对象的部分扩展
2017/02/20 Javascript
详谈js中数组(array)和对象(object)的区别
2017/02/27 Javascript
Vue2.0用 watch 观察 prop 变化(不触发)
2017/09/08 Javascript
通过jquery获取上传文件名称、类型和大小的实现代码
2018/04/19 jQuery
electron中使用bootstrap的示例代码
2018/11/06 Javascript
基于vue实现一个神奇的动态按钮效果
2019/05/15 Javascript
基于layui轮播图满屏是高度自适应的解决方法
2019/09/16 Javascript
Vue3.0 响应式系统源码逐行分析讲解
2019/10/14 Javascript
使用p5.js临摹动态图形
2019/10/23 Javascript
Python实现删除Android工程中的冗余字符串
2015/01/19 Python
编写Python CGI脚本的教程
2015/06/29 Python
python版简单工厂模式
2017/10/16 Python
使用Python+wxpy 找出微信里把你删除的好友实例
2019/02/21 Python
Python3.5多进程原理与用法实例分析
2019/04/05 Python
python自动发邮件总结及实例说明【推荐】
2019/05/31 Python
python如何从文件读取数据及解析
2019/09/19 Python
pycharm中使用request和Pytest进行接口测试的方法
2020/07/31 Python
Python confluent kafka客户端配置kerberos认证流程详解
2020/10/12 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
社会实践感言
2014/01/25 职场文书
自荐信如何制作?
2014/02/21 职场文书
财务内勤岗位职责
2014/04/17 职场文书
员工安全生产责任书
2014/07/22 职场文书
2015年中学图书馆工作总结
2015/07/22 职场文书
创业计划书之酒吧
2019/12/02 职场文书
SpringBoot整合JWT的入门指南
2021/06/29 Java/Android
Python中的pprint模块
2021/11/27 Python