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 相关文章推荐
ASP知识讲座四
Oct 09 PHP
php 正则表达式小结
Aug 31 PHP
php数据库连接时容易出错的特殊符号问题
Sep 01 PHP
PHP对MongoDB[NoSQL]数据库的操作
Mar 01 PHP
php调整gif动画图片尺寸示例代码分享
Dec 05 PHP
ThinkPHP让分页保持搜索状态的方法
Jul 02 PHP
十个PHP高级应用技巧果断收藏
Sep 25 PHP
PHP正则表达式入门教程(推荐)
May 18 PHP
php实现XML和数组的相互转化功能示例
Feb 08 PHP
ThinkPHP删除栏目(实现批量删除栏目)
Jun 21 PHP
strpos() 函数判断字符串中是否包含某字符串的方法
Jan 16 PHP
在 Laravel 项目中使用 webpack-encore的方法
Jul 21 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/03/10 PHP
浅析php中常量,变量的作用域和生存周期
2013/08/10 PHP
laravel 解决crontab不执行的问题
2019/10/22 PHP
php实现的证件照换底色功能示例【人像抠图/换背景图】
2020/05/29 PHP
TimergliderJS 一个基于jQuery的时间轴插件
2011/12/07 Javascript
打印json对象的内容及JSON.stringify函数应用
2013/03/29 Javascript
JS命名空间的另一种实现
2013/08/09 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
js实现九宫格图片半透明渐显特效的方法
2015/02/16 Javascript
javascript实现数组中的内容随机输出
2015/08/11 Javascript
写给小白的JavaScript引擎指南
2015/12/04 Javascript
轻松实现js选项卡切换效果
2016/09/24 Javascript
javascript实现复选框全选或反选
2017/02/04 Javascript
jQuery 同时获取多个标签的指定内容并储存为数组
2018/11/20 jQuery
更优雅的微信小程序骨架屏实现详解
2019/08/07 Javascript
[02:07]2017国际邀请赛中国区预选赛直邀战队前瞻
2017/06/23 DOTA
python 从远程服务器下载东西的代码
2013/02/10 Python
python MNIST手写识别数据调用API的方法
2018/08/08 Python
Python异常处理操作实例详解
2018/08/28 Python
用pyqt5 给按钮设置图标和css样式的方法
2019/06/24 Python
浅谈python3打包与拆包在函数的应用详解
2020/05/02 Python
浅谈Python __init__.py的作用
2020/10/28 Python
基于python+selenium自动健康打卡的实现代码
2021/01/13 Python
Pycharm 设置默认解释器路径和编码格式的操作
2021/02/05 Python
pytorch 把图片数据转化成tensor的操作
2021/03/04 Python
五个2015 年最佳HTML5 框架
2015/11/11 HTML / CSS
AmazeUI 缩略图的实现示例
2020/08/18 HTML / CSS
雅诗兰黛旗下专业男士保养领导品牌:Lab Series
2017/05/15 全球购物
ASICS印度官方网站:日本专业运动品牌
2020/06/20 全球购物
波兰多品牌运动商店:StreetStyle24.pl
2020/09/22 全球购物
大学毕业生求职自荐书
2014/06/05 职场文书
本科应届生自荐信
2014/06/29 职场文书
2015年春节标语口号
2014/12/09 职场文书
中学推普周活动总结
2015/05/07 职场文书
七年级语文教学反思
2016/03/03 职场文书
SQL SERVER实现连接与合并查询
2022/02/24 SQL Server