• PHP中for和foreach背后发生了什么和关于迭代器的理解


    for和foreach简单描述

    php中的for处理方式类似于c语言,只要expr2表达式为真,则循环会一直继续下去:

    for (expr1; expr2; expr3)
        statement
    

    php中的foreach主要是为了遍历数组和对象:
    foreach开始执行的时候,数组内部的指针会自动指向第一个单元,每进行一次循环,数组和对象的内部指针为自动移动一位,尽量在移动的时候不要修改其值.

    foreach (array_expression as $value)
        statement
    foreach (array_expression as $key => $value)
        statement
    

    迭代器

    上述的forforeach描述很简单.

    foreach能够循环任何迭代器对象,而这些对象不仅仅是数组,可以是任何类型的对象.
    一个迭代器是一个对象,迭代器对象可能是一个数组,也可能是一个目录,甚至可以是数据库查询结果集.

    SPL(the Standard PHP Library)通过内建的类,提供了很大数量的迭代器,从而让代码更有效,更可读.

    The DirectoryIterator class

    try {
        $iterator = new DirectoryIterator($directory);
        foreach ($iterator as $info) {
            if (!$info->isDot() && $info->isFile()) {
                echo $info->__toString() . "
    ";
            }
        }
    } catch (Exception $e) {
        echo get_class($e) . ": " . $e->getMessage();
    }
    

    ArrayIterator

    $arr = ["java", "python", "php"];
    $iter = new ArrayIterator($arr);
    foreach ($iter as $key => $value) {
        echo $key . ":  " . $value . "
    ";
    }
    

    看一个另类的用法:

    $val = ["shell", "python", "php"];
    $arr = new ArrayIterator($val);
    while ($arr->valid()) {
        echo $arr->key() . " : " . $arr->current() . ":" . $arr->offsetGet($arr->key()) . PHP_EOL;
        $arr->offsetSet($arr->key(), "ok");
        $arr->next();
    }
    print_r($arr->getArrayCopy());
    

    next()方法就是进行指针移动的关键

    为什么使用迭代器

    • 在处理具有大量数据的对象时,使用迭代器比数组更有效,因为在foreach迭代数组的时候会拷贝数组对象,而SPL迭代器通过内部封装每一次只会输出一个元素则更有效.
    • 延迟加载,迭代器在使用的时候能够加载仅仅需要的数据
    • 迭代器真正有用点在于用途比较广泛,能够通过实现迭代器接口创造出更多的数据结构

    如何创建一个自定义迭代器

    SPL迭代器类已经提供了很多功能的迭代器,PHP也提供了接口Iterator,IteratorAggregate让程序员创建自定义的迭代器类.

    只要实现接口Iterator的五个方法就可以创建一个迭代器类,rewind(),current(), key(),next(),valid()

    当迭代开始,PHP调用rewind()方法让指针回到数据集开始处,通过调用valid()方法检查数据是否可用,假如返回为true,则调用current()方法获取当前指针对应的值,同时key()能够获取到当前指针的key,最后再调用next()方法重复上述的流程.

    class myIterator implements Iterator {
    }
    

    IteratorAggregate
    Iterator接口比较适合于创建一个内部的迭代器,理想的情况下,使用IteratorAggregate更加适合创建一个外部的迭代器,只要实现getIterator()方法即可.

    IteratorAggregateIterator的关系类似于容器和具体容器的关系

    class myIteratorAggregate implements IteratorAggregate {
    
        protected $arr = array("php", "python", "shell");
        protected $type;
    
        function __construct($type = 1) {
            $this->type = $type;
        }
    
        public function getIterator() {
            if ($this->type == 1)
                return new ArrayIterator($this->arr);
            else
                return new myIterator($this->arr);
        }
    }
    $obj = new myIteratorAggregate ;
    foreach ($obj as $v) {
        echo $v . "
    ";
    }
    

    总结:

    • 理解迭代器很容易,但是创建一个有意义的迭代器则不容易,这就类似于学习算法可能很容易,但如何实际运用则是另外一回事.
    • 通过SPL迭代器,避免了程序员自造轮子,同时也提供了更多的数据结构.
    • 至于使用数组还是迭代器,则要根据实际情况,比如从效率,可读性等方面衡量.
    • 通过SPL类和接口,PHP提供了更多扩展,这也是PHP越来越现代化的证明.
  • 相关阅读:
    查询job的几个语句
    fdisk与parted分区
    升级时针对Source oracle home 不存在解决办法
    oracle常用视图v$mystat v$sesstat v$sysstat v$statname v$thread v$ parameter v$session v$process
    x$ksppi与x$ksppcv查询隐藏参数
    查询表空间及已使用情況的SQL语句
    通过系统进程查找sql语句
    RAC日常维护命令
    创建ASM实例及ASM数据库(转载)
    安装数据库软件,节点未显示
  • 原文地址:https://www.cnblogs.com/usays/p/10640870.html
Copyright © 2020-2023  润新知