zoukankan      html  css  js  c++  java
  • Php-SPL库中的迭代器类详解(转)

    SPL提供了多个迭代器类,分别提供了迭代访问、过滤数据、缓存结果、控制分页等功能。,因为php总是在不断壮大,我尽可能列出SPL中所有的迭代类。下面其中一些迭代器类是需要php5.4,另外一些如SearhIteratoer类在最新的php版本中已经去除

    1.ArrayIteratoer

    PHP数组创建一个迭代器,当其和IteratorAggregate类一起使用时,免去了直接实现Iterator接口的方法的工作。

    <示例>

     1 $b = array(
     2     'name'=> 'mengzhi',
     3     'age' => '12',
     4     'city'=> 'shanghai'
     5 );
     6 $a = new ArrayIterator($b);
     7 $a->append(array(
     8                 'home' => 'china',
     9                 'work' => 'developer'
    10            ));
    11 $c = $a->getArrayCopy();
    12 print_r($a);
    13 print_r($c);
    14 
    15 /**output
    16 ArrayIterator Object
    17 (
    18     [storage:ArrayIterator:private] => Array
    19     (
    20     [name] => mengzhi
    21             [age] => 12
    22             [city] => shanghai
    23             [0] => Array
    24     (
    25     [home] => china
    26                     [work] => developer
    27                 )
    28 
    29         )
    30 
    31 )
    32 Array
    33     (
    34     [name] => mengzhi
    35     [age] => 12
    36     [city] => shanghai
    37     [0] => Array
    38     (
    39     [home] => china
    40             [work] => developer
    41         )
    42 
    43 )
    44 **/

    2. LimitIterator

    返回给定数量的结果以及从集合中取出结果的起始索引点:

    <示例>

     1 // Create an iterator to be limited
     2 $fruits = new ArrayIterator(array(
     3                                  'apple',
     4                                  'banana',
     5                                  'cherry',
     6                                  'damson',
     7                                  'elderberry'
     8                             ));
     9 // Loop over first three fruits only
    10 foreach (new LimitIterator($fruits, 0, 3) as $fruit) {
    11     var_dump($fruit);
    12 }
    13 echo "
    ";
    14 // Loop from third fruit until the end
    15 // Note: offset starts from zero for apple
    16 foreach (new LimitIterator($fruits, 2) as $fruit) {
    17     print_r($fruit);
    18 }
    19 
    20 /**output
    21 string(5) "apple"
    22 string(6) "banana"
    23 string(6) "cherry"
    24 
    25 cherrydamsonelderberry
    26  */

    3. AppendIterator

      按顺序迭代访问几个不同的迭代器。例如,希望在一次循环中迭代访问两个或者更多的组合。这个迭代器的append方法类似于array_merge()函数来合并数组。

     1 $array_a = new ArrayIterator(array('a', 'b', 'c'));
     2 $array_b = new ArrayIterator(array('d', 'e', 'f'));
     3 $iterator = new AppendIterator;
     4 $iterator->append($array_a);
     5 $iterator->append($array_b);
     6 foreach ($iterator as $current) {
     7     echo $current."
    ";
     8 }
     9 /**output
    10 a
    11 b
    12 c
    13 d
    14 e
    15 f
    16  */

    4. FilterIterator

    基于OuterIterator接口,用于过滤数据,返回符合条件的元素。必须实现一个抽象方法accept(),此方法必须为迭代器的当前项返回truefalse

     1 class UserFilter extends FilterIterator
     2 {
     3     private $userFilter;
     4 
     5     public function __construct(Iterator $iterator, $filter)
     6     {
     7         parent::__construct($iterator);
     8         $this->userFilter = $filter;
     9     }
    10 
    11     public function accept()
    12     {
    13         $user = $this->getInnerIterator()->current();
    14         if (strcasecmp($user['name'], $this->userFilter) == 0) {
    15             return false;
    16         }
    17         return true;
    18     }
    19 }
    20 
    21 $array = array(
    22     array(
    23         'name' => 'Jonathan',
    24         'id'   => '5'
    25     ),
    26     array(
    27         'name' => 'Abdul',
    28         'id'   => '22'
    29     )
    30 );
    31 $object = new ArrayObject($array);
    32 //去除掉名为abdul的人员
    33 $iterator = new UserFilter($object->getIterator(), 'abdul');
    34 foreach ($iterator as $result) {
    35     echo $result['name'];
    36 }
    37 
    38 /**output
    39 Jonathan
    40 **/

    5. RegexIterator

    继承FilterIterator,支持使用正则表达式模式匹配和修改迭代器中的元素。经常用于将字符串匹配。

     1 $a = new ArrayIterator(array('test1', 'test2', 'test3'));
     2 $i = new RegexIterator($a, '/^(test)(d+)/', RegexIterator::REPLACE);
     3 $i->replacement = '$2:$1';
     4 print_r(iterator_to_array($i));
     5 
     6 /**output
     7 Array
     8 (
     9     [0] => 1:test
    10     [1] => 2:test
    11     [2] => 3:test
    12 )
    13  **/

    6. IteratorIterator

    一种通用类型的迭代器,所有实现了Traversable接口的类都可以被它迭代访问。

    7. CachingIterator

    用来执行提前读取一个元素的迭代操作,例如可以用于确定当前元素是否为最后一个元素。

     1 $array = array('koala', 'kangaroo', 'wombat', 'wallaby', 'emu', 'kiwi', 'kookaburra', 'platypus');
     2 try {
     3     $object = new CachingIterator(new ArrayIterator($array));
     4     foreach ($object as $value) {
     5         echo $value;
     6         if ($object->hasNext()) {
     7             echo ',';
     8         }
     9     }
    10 }
    11 catch (Exception $e) {
    12     echo $e->getMessage();
    13 }
    14 /**output
    15 koala,kangaroo,wombat,wallaby,emu,kiwi,kookaburra,platypus
    16  **/

    8. SeekableIterator

    用于创建非顺序访问的迭代器,允许跳转到迭代器中的任何一点上。

    1 $array = array("apple", "banana", "cherry", "damson", "elderberry");
    2 $iterator = new ArrayIterator($array);
    3 $iterator->seek(3);
    4 echo $iterator->current();
    5 /**output
    6 damson
    7  **/

    9. NoRewindIterator

    用于不能多次迭代的集合,适用于在迭代过程中执行一次性操作。

     1 $fruit = array('apple', 'banana', 'cranberry');
     2 $arr = new ArrayObject($fruit);
     3 $it = new NoRewindIterator($arr->getIterator());
     4 echo "Fruit A:
    ";
     5 foreach ($it as $item) {
     6     echo $item . "
    ";
     7 }
     8 
     9 echo "Fruit B:
    ";
    10 foreach ($it as $item) {
    11     echo $item . "
    ";
    12 }
    13 /**output
    14 Fruit A:
    15 apple
    16 banana
    17 cranberry
    18 Fruit B:
    19  **/

    10. EmptyIterator

    一种占位符形式的迭代器,不执行任何操作。当要实现某个抽象类的方法并且这个方法需要返回一个迭代器时,可以使用这种迭代器。

    11. InfiniteIterator

    用于持续地访问数据,当迭代到最后一个元素时,会再次从第一个元素开始迭代访问。

     1 $arrayit = new ArrayIterator(array('cat', 'dog'));
     2 $infinite = new InfiniteIterator($arrayit);
     3 $limit = new LimitIterator($infinite, 0, 7);
     4 foreach ($limit as $value) {
     5     echo "$value
    ";
     6 }
     7 /**output
     8 cat
     9 dog
    10 cat
    11 dog
    12 cat
    13 dog
    14 cat
    15  **/

    12. RecursiveArrayIterator

    创建一个用于递归形式数组结构的迭代器,类似于多维数组.它为许多更复杂的迭代器提供了所需的操作,如RecursiveTreeIterator和RecursiveIteratorIterator迭代器。

    $fruits = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
    $iterator = new RecursiveArrayIterator($fruits);
    while ($iterator->valid()) {
        //检查是否含有子节点
        if ($iterator->hasChildren()) {
            //输出所以字节点
            foreach ($iterator->getChildren() as $key => $value) {
                echo $key . ' : ' . $value . "
    ";
            }
        } else {
            echo "No children.
    ";
        }
        $iterator->next();
    }
    
    /**output
    No children.
    No children.
    a : apple
    p : pear
     **/

    13. RecursiveIteratorIterator

    将一个树形结构的迭代器展开为一维结构。

     1 $fruits = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
     2 $arrayiter = new RecursiveArrayIterator($fruits);
     3 $iteriter = new RecursiveIteratorIterator($arrayiter);
     4 foreach ($iteriter as $key => $value) {
     5     $d = $iteriter->getDepth();
     6     echo "depth=$d k=$key v=$value
    ";
     7 }
     8 
     9 /**output
    10 depth=0 k=a v=lemon
    11 depth=0 k=b v=orange
    12 depth=1 k=a v=apple
    13 depth=1 k=p v=pear
    14  **/

    14. RecursiveTreeIterator

    以可视在方式显示一个树形结构。

     1 $hey = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
     2 $awesome = new RecursiveTreeIterator(
     3     new RecursiveArrayIterator($hey),
     4     null, null, RecursiveIteratorIterator::LEAVES_ONLY
     5 );
     6 foreach ($awesome as $line)
     7     echo $line . PHP_EOL;
     8 
     9 /**output
    10 |-lemon
    11 |-orange
    12     |-apple
    13     -pear
    14  **/

    15. ParentIterator

    是一个扩展的FilterIterator迭代器,它可以过滤掉来自于RecursiveIterator迭代器的非父元素,只找出子节点的键值。通俗来说,就是去枝留叶。

     1 $hey = array("a" => "lemon", "b" => "orange", array("a" => "apple", "p" => "pear"));
     2 $arrayIterator = new RecursiveArrayIterator($hey);
     3 $it = new ParentIterator($arrayIterator);
     4 print_r(iterator_to_array($it));
     5 /**output
     6 Array
     7     (
     8     [0] => Array
     9     (
    10         [a] => apple
    11         [p] => pear
    12     )
    13 )
    14  **/

    16. RecursiveFilterIterator

    FilterIterator迭代器的递归形式,也要求实现抽象的accept()方法,但在这个方法中应该使用$this->getInnerIterator()方法访问当前正在迭代的迭代器。

     1 class TestsOnlyFilter extends RecursiveFilterIterator
     2 {
     3     public function accept()
     4     {
     5         // 找出含有“叶”的元素
     6         return $this->hasChildren() || (mb_strpos($this->current(), "叶") !== FALSE);
     7     }
     8 }
     9 
    10 $array = array("叶1", array("李2", "叶3", "叶4"), "叶5");
    11 $iterator = new RecursiveArrayIterator($array);
    12 $filter = new TestsOnlyFilter($iterator);
    13 $filter = new RecursiveIteratorIterator($filter);
    14 print_r(iterator_to_array($filter));
    15 /**output
    16 Array
    17 (
    18     [0] => 叶1
    19     [1] => 叶3
    20     [2] => 叶5
    21 )
    22 **/

    17. RecursiveRegexIterator

    RegexIterator迭代器的递归形式,只接受RecursiveIterator迭代器作为迭代对象。

     1 $rArrayIterator = new RecursiveArrayIterator(array('叶1', array('tet3', '叶4', '叶5')));
     2 $rRegexIterator = new RecursiveRegexIterator($rArrayIterator, '/^叶/',
     3     RecursiveRegexIterator::ALL_MATCHES);
     4 
     5 foreach ($rRegexIterator as $key1 => $value1) {
     6     if ($rRegexIterator->hasChildren()) {
     7         // print all children
     8         echo "Children: ";
     9         foreach ($rRegexIterator->getChildren() as $key => $value) {
    10             echo $value . " ";
    11         }
    12         echo "
    ";
    13     } else {
    14         echo "No children
    ";
    15     }
    16 }
    17 /**output
    18 No children
    19 Children: 叶4 叶5 
    20  **/

    18. RecursiveCachingIterator

    在RecursiveIterator迭代器上执行提前读取一个元素的递归操作。


    19. CallbackFilterIterator(PHP5.4)

    同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。

     1 $hey = array( "李1", "叶2", "叶3", "叶4", "叶5", "叶6",);
     2 $arrayIterator = new RecursiveArrayIterator($hey);
     3 function isYe($current)
     4 {
     5     return mb_strpos($current,'叶') !== false;
     6 }
     7 
     8 $rs = new CallbackFilterIterator($arrayIterator, 'isYe');
     9 print_r(iterator_to_array($rs));
    10 
    11 /**output
    12 Array
    13 (
    14     [0] => 叶2
    15     [1] => 叶3
    16     [2] => 叶4
    17     [3] => 叶5
    18     [4] => 叶6
    19 )
    20  **/

    20. DirectoryIterator

    目录文件遍历器

    方    法

    描    述

    DirectoryIterator::getSize

    得到文件大小

    DirectoryIterator::getType

    得到文件类型

    DirectoryIterator::isDir

    如果当前项是一个目录,返回true

    DirectoryIterator::isDot

    如果当前项是...,返回true

    DirectoryIterator::isExecutable

    如果文件可执行,返回true

    DirectoryIterator::isFile

    如果文件是一个常规文件,返回true

    DirectoryIterator::isLink

    如果文件是一个符号链接,返回true

    DirectoryIterator::isReadable

    如果文件可读,返回true

    DirectoryIterator::isWritable

    如果文件可写,返回true

    DirectoryIterator::key

    返回当前目录项

    DirectoryIterator::next

    移动到下一项

    DirectoryIterator::rewind

    将目录指针返回到开始位置

    DirectoryIterator::valid

    检查目录中是否包含更多项

    1 $it = new DirectoryIterator("../");
    2 foreach ($it as $file) {
    3     //用isDot ()方法分别过滤掉“.”和“..”目录
    4     if (!$it->isDot()) {
    5         echo $file . "
    ";
    6     }
    7 }

    21. RecursiveDirectoryIterator

    递归目录文件遍历器,可实现列出所有目录层次结构,而不是只操作一个目录。

    方    法

    描    述

    RecursiveDirectoryIterator::getChildren

    如果这是一个目录,为当前项返回一个迭代器

    RecursiveDirectoryIterator::hasChildren

    返回当前项是否是一个目录而不是...

    RecursiveDirectoryIterator::key

    返回当前目录项的路径和文件名

    RecursiveDirectoryIterator::next

    移动到下一项

    RecursiveDirectoryIterator::rewind

    将目录指针返回到开始位置

    RecursiveIteratorIterator::current

    访问当前元素值

    RecursiveIteratorIterator::getDepth

    得到递归迭代的当前深度

    RecursiveIteratorIterator::getSubIterator

    得到当前活动子迭代器

    RecursiveIteratorIterator::key

    访问当前键

    RecursiveIteratorIterator::next

    前移到下一个元素

    RecursiveIteratorIterator::rewind

    将迭代器返回到顶级内层迭代器的第一个元素

    RecursiveIteratorIterator::valid

    检查当前位置是否合法

    1 //列出指定目录中所有文件
    2 $path = realpath('../');
    3 $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
    4 foreach ($objects as $name => $object) {
    5     echo "$name
    ";
    6 }

    22. FilesystemIterator

    DirectoryIterator的遍历器

    1 $it = new FilesystemIterator('../');
    2 foreach ($it as $fileinfo) {
    3     echo $fileinfo->getFilename() . "
    ";
    4 }

    23. GlobIterator

    带匹配模式的文件遍历器

    //找出../目录中.php扩展名的文件
    $iterator = new GlobIterator('./*.php');
    if (!$iterator->count()) {
        echo '无php文件';
    } else {
        $n = 0;
        printf("总计 %d 个php文件
    ", $iterator->count());
        foreach ($iterator as $item) {
            printf("[%d] %s
    ", ++$n, $iterator->key());
        }
    }
    /**output
    总计 23 个php文件
    [1] .1.php
    [2] .11.php
    [3] .12.php
    [4] .13.php
    [5] .14.php
    [6] .15.php
    [7] .16.php
    [8] .17.php
    [9] .19.php
    [10] .2.php
    [11] .20.php
    [12] .21.php
    [13] .22.php
    [14] .23.php
    [15] .24.php
    [16] .25.php
    [17] .26.php
    [18] .3.php
    [19] .4.php
    [20] .5.php
    [21] .7.php
    [22] .8.php
    [23] .9.php
     **/

    24. MultipleIterator

    用于迭代器的连接器,具体看示例

     1 $person_id = new ArrayIterator(array('001', '002', '003'));
     2 $person_name = new ArrayIterator(array('张三', '李四', '王五'));
     3 $person_age = new ArrayIterator(array(22, 23, 11));
     4 $mit = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);
     5 $mit->attachIterator($person_id, "ID");
     6 $mit->attachIterator($person_name, "NAME");
     7 $mit->attachIterator($person_age, "AGE");
     8 echo "连接的迭代器个数:".$mit->countIterators() . "
    "; //3
     9 foreach ($mit as $person) {
    10     print_r($person);
    11 }
    12 /**output
    13 Array
    14 (
    15     [ID] => 001
    16     [NAME] => 张三
    17     [AGE] => 22
    18 )
    19 Array
    20 (
    21     [ID] => 002
    22     [NAME] => 李四
    23     [AGE] => 23
    24 )
    25 Array
    26 (
    27     [ID] => 003
    28     [NAME] => 王五
    29     [AGE] => 11
    30 )
    31  **/

    25. RecursiveCallbackFilterIterator(PHP5.4)

    RecursiveIterator迭代器上进行递归操作,同时执行过滤和回调操作,在找到一个匹配的元素之后会调用回调函数。

     1 function doesntStartWithLetterT($current)
     2 {
     3     $rs = $current->getFileName();
     4     return $rs[0] !== 'T';
     5 }
     6 
     7 $rdi = new RecursiveDirectoryIterator(__DIR__);
     8 $files = new RecursiveCallbackFilterIterator($rdi, 'doesntStartWithLetterT');
     9 foreach (new RecursiveIteratorIterator($files) as $file) {
    10     echo $file->getPathname() . PHP_EOL;
    11 }

    26. SimpleXMLIterator

    XMl文档访问迭代器,可实现访问xml中所有节点

     1 $xml = <<<XML
     2 <books>
     3     <book>
     4         <title>PHP Basics</title>
     5         <author>Jim Smith</author>
     6     </book>
     7     <book>XML basics</book>
     8 </books>
     9 XML;
    10 // SimpleXML转换为数组
    11 function sxiToArray($sxi)
    12 {
    13     $a = array();
    14     for ($sxi->rewind(); $sxi->valid(); $sxi->next()) {
    15         if (!array_key_exists($sxi->key(), $a)) {
    16             $a[$sxi->key()] = array();
    17         }
    18         if ($sxi->hasChildren()) {
    19             $a[$sxi->key()][] = sxiToArray($sxi->current());
    20         } else {
    21             $a[$sxi->key()][] = strval($sxi->current());
    22         }
    23     }
    24     return $a;
    25 }
    26 
    27 $xmlIterator = new SimpleXMLIterator($xml);
    28 $rs = sxiToArray($xmlIterator);
    29 print_r($rs);
    30 /**output
    31 Array
    32 (
    33     [book] => Array
    34         (
    35             [0] => Array
    36                 (
    37                     [title] => Array
    38                         (
    39                             [0] => PHP Basics
    40                         )
    41 
    42                     [author] => Array
    43                         (
    44                             [0] => Jim Smith
    45                         )
    46 
    47                 )
    48 
    49             [1] => XML basics
    50         )
    51 
    52 )
    53  **/
  • 相关阅读:
    PAT 1097. Deduplication on a Linked List (链表)
    PAT 1096. Consecutive Factors
    PAT 1095. Cars on Campus
    PAT 1094. The Largest Generation (层级遍历)
    PAT 1093. Count PAT's
    PAT 1092. To Buy or Not to Buy
    PAT 1091. Acute Stroke (bfs)
    CSS:word-wrap/overflow/transition
    node-webkit中的requirejs报错问题:path must be a string error in Require.js
    script加载之defer和async
  • 原文地址:https://www.cnblogs.com/xingmeng/p/3583204.html
Copyright © 2011-2022 走看看