摘要:將數(shù)組或者集合中的全部或者一部數(shù)據(jù)取出來,用迭代器比較方便迭代器能陸續(xù)遍歷幾個迭代器按順序迭代訪問幾個不同的迭代器。
一、SPL簡介
?????什么是SPL
PHP的標準庫SPL:Standard PHP Library
?????SPL: 用于解決常見普遍問題的一組接口與類的集合
?????Common Problem:
數(shù)學建模/數(shù)據(jù)結構
解決數(shù)據(jù)怎么存儲的問題
元素遍歷
數(shù)據(jù)怎么查看問題
常用方法的統(tǒng)一調用
通用方法(數(shù)組、集合的大小)
自定義遍歷
類定義的自動裝載
讓PHP程序適應大型項目的管理要求,把功能的實現(xiàn)分散到不同的文件中
?????SPL的基本框架
?????
二、SPL的常用數(shù)據(jù)結構?????
2.1 雙向鏈表 2.1.1 雙向鏈表簡介?????
?????Bottom:最先添加到鏈表中的節(jié)點叫做Bottom(底部),也稱為頭部(head)
?????Top:最后添加到鏈表中得節(jié)點叫做top頂部,也稱為尾部
?????鏈表指針:是一個當前關注的節(jié)點的標識,可以指向任意節(jié)點
?????當前指針:鏈表指針指向的節(jié)點稱為當前節(jié)點
?????節(jié)點名稱:可以在鏈表中唯一標識一個節(jié)點的名稱,我們通常又稱為節(jié)點的key或offset
?????節(jié)點數(shù)據(jù):存放在鏈表中的應用數(shù)據(jù),通常稱為value
/** * 雙向鏈表 */ $obj = new SplDoublyLinkedList(); $obj->push(4); $obj->push(6); $obj->unshift(66); print_r($obj);
SplDoublyLinkedList Object ( [flags:SplDoublyLinkedList:private] => 0 [dllist:SplDoublyLinkedList:private] => Array ( [0] => 66 [1] => 4 [2] => 6 ) )
?????雙向鏈表常用方法:
?????Bottom: 獲得鏈表底部(頭部)元素,當前指針位置不變
?????Top: 獲取鏈表頂部(尾部)元素,當前指針位置不變
?????Push: 往鏈表頂部(Top)中追加節(jié)點
?????Pop: 把top位置的節(jié)點從鏈表中刪除,操作不改變當前指針的位置
?????Unshif: 往鏈表底部追加節(jié)點(Bottom)
?????Shif: 刪除鏈表底部的節(jié)點
?????Rewind: 把節(jié)點指針指向Bottom所在的節(jié)點
?????Current: 指向鏈表當前節(jié)點的指針,必須在調用之前先調用rewind。當指向的節(jié)點被刪除之后,會指向一個空節(jié)點
?????Next: 指針指向下一個節(jié)點,current的返回值隨之改變
?????Prev: 指針指向上一個節(jié)點,current的返回值隨之改變
?????雙向鏈表判斷當前節(jié)點是否有效節(jié)點方法:
if(雙向鏈表對象.current()) 有效 else 無效
?????或
//用$obj->current()判斷當前是否有迭代元素不好,因為當元素值是false,0,或者空字符時 //他們效果和null一樣,區(qū)分不了,所以嚴謹?shù)脑捯褂胿alid方法判斷 if(雙向鏈表對象.valid()) 有效 else 無效2.2 堆棧 2.2.1 堆棧簡介
?????繼承自SplDoublyLinkedList類的SplStack類
?????操作:
- `push`:壓入堆棧(存入) - `pop`:退出堆棧(取出)
?????堆棧:單端出入,先進后出 Fist In Last Out(FILO)
2.2.2 堆棧代碼實踐/** * 堆棧 */ $obj = new SplStack(); $obj->push(2); $obj->push("test"); $obj->push(6); print_r($obj);
SplStack Object ( [flags:SplDoublyLinkedList:private] => 6 [dllist:SplDoublyLinkedList:private] => Array ( [0] => 2 [1] => test [2] => 6 ) )
?????常用操作:
?????Bottom(): 最先進入的元素;
?????Top(): 最后進入的元素;
?????offSet(0): 是top的位置
?????rewind(): 把top的元素置為current()的位置
?????注意:
- 堆棧的`rewind()`指向`top`,雙向鏈表的`rewind()`指向`bottom` - 堆棧和雙向鏈表都有`next`方法,方向相反2.3 隊列
?????隊列和堆棧剛好相反,最先進入隊列的元素會最先走出隊列
?????繼承自SplDoublyLinkedList類的SqlQueue類
?????操作:
- `enqueue`:進入隊列 - `dequeue`:退出隊列
/** * 隊列 */ $obj = new SplQueue(); $obj->enqueue("a"); $obj->enqueue("b"); $obj->enqueue("c"); print_r($obj);
SplQueue Object ( [flags:SplDoublyLinkedList:private] => 4 [dllist:SplDoublyLinkedList:private] => Array ( [0] => a [1] => b [2] => c ) )
?????常用操作:
?????enqueue: 插入一個節(jié)點到隊列里面的top位置
?????dequeue: 操作從隊列中提取Bottom位置的節(jié)點,同時從隊列里面刪除該元素
?????offSet(0): 是Bottom所在的位置
?????rewind: 操作使得指針指向Bottom所在的位置的節(jié)點
?????next: 操作使得當前指針指向Top方向的下一個節(jié)點
通過某種 統(tǒng)一的方式 遍歷鏈表或則數(shù)組中的元素的過程叫做迭代遍歷,這種統(tǒng)一的遍歷工具叫迭代器
?????PHP中迭代器是通過Iterator接口定義的
3.2 ArrayIterator迭代器?????ArrayIterator迭代器用于遍歷數(shù)組
seek(),指針定位到某個位置,很實用,跳過前面n-1的元素
ksort(),對key進行字典序排序
asort(),對值進行字典序排序
$arr=array( "apple" => "apple value", // position = 0 "orange" => "orange value", // position = 1 "grape" => "grape value", "plum" => "plum value" ); $obj=new ArrayObject($arr); $it =$obj->getIterator();//生成數(shù)組的迭代器。 foreach ($it as $key => $value){ echo $key . ":". $value ."
"; } echo "
"; //實現(xiàn)和foreach同樣功能 $it->rewind();// 調用current之前一定要調用rewind While($it->valid()){//判斷當前是否為有效數(shù)據(jù) echo $it->key()." : ".$it->current()."
"; $it->next();//千萬不能少 } //實現(xiàn)更復雜功能,跳過某些元素進行打印 $it->rewind(); if ($it->valid()){ $it->seek(1);//position,跳過前面 n-1的元素 While($it->valid()){//判斷當前是否為有效數(shù)據(jù) echo $it->key()." : ".$it->current()."
"; $it->next();//千萬不能少 } } $it->ksort();//對key進行字典序排序 //$it->asort();//對值進行字典序排序 foreach ($it as $key => $value){ echo $key . ":". $value ."
"; }
?????foreach本質會自動生成一個迭代器,只是使用了迭代器的最長用功能,如果要實現(xiàn)復雜需求,foreach實現(xiàn)不了,就需要手動生成迭代器對象來使用了
?????比如,要從一個大數(shù)組中取出一部分數(shù)據(jù),foreach比較困難,除非他知道數(shù)據(jù)的樣子。將數(shù)組或者集合中的全部或者一部數(shù)據(jù)取出來,用迭代器比較方便
?????AppendIterator能陸續(xù)遍歷幾個迭代器
按順序迭代訪問幾個不同的迭代器。例如,希望在一次循環(huán)中迭代訪問兩個或者更多的組合
$arr_a = new ArrayIterator(array("a"=> array("a","b"=>234),"b","c")); $arr_b = new ArrayIterator(array("d","e","f")); $it = new AppendIterator(); $it->append($arr_a);//追加數(shù)組 $it->append($arr_b);//追加數(shù)組,然后遍歷$it foreach ($it as $key => $value){ print_r($value); }3.4 MultipleIterator迭代器
?????用于把多個Iterator里面的數(shù)據(jù)組合成為一個整體來訪問
Multipleiterator將多個arrayiterator拼湊起來
Appenditerator將多個arrayiteratorr連接起來
$idIter = new ArrayIterator(array("01","02","03")); $nameIter = new ArrayIterator(array("張三","李四","王五")); $ageIter = new ArrayIterator(array("22","23","25")); $mit = new MultipleIterator(MultipleIterator::MIT_KEYS_ASSOC);//按照key關聯(lián) $mit->attachIterator($idIter,"ID"); $mit->attachIterator($nameIter,"NAME"); $mit->attachIterator($ageIter,"AGE"); foreach ($mit as $value){ print_r($value); }
Array ( [ID] => 01 [NAME] => 張三 [AGE] => 22 ) Array ( [ID] => 02 [NAME] => 李四 [AGE] => 23 ) Array ( [ID] => 03 [NAME] => 王五 [AGE] => 25 )四、SPL的基礎接口 4.1 最常用的接口
Countable:繼承了該接口的類可以直接調用count(),得到元素個數(shù)
OuterIterator:,如果想對迭代器進行一定的處理之后再返回,可以用這個接口,相當于進行了一次封裝,對原來的進行一定的處理
RecursiveIterator:,可以對多層結構的迭代器進行迭代,比如遍歷一棵樹,類似于filesystemIterator
SeekableIterator:,可以通過seek方法定位到集合里面的某個特定元素
4.2 Countable?????在代碼里面經??梢灾苯佑?b>count($obj)方法獲取對象里面的元素個數(shù)
count(array("name"=>"Peter","id"=>"5"));
?????對于我們定義的類,也能這樣訪問嗎?
如果對象本身也有count函數(shù),但是沒有繼承countable接口,直接用count函數(shù)時,不會調用對象自定義的count
如果對象本身也有count函數(shù),同時對象也繼承了countable接口,直接用count函數(shù)時,會調用對象自身的count函數(shù),效果相當與:對象->count()
count()是Countable必須實現(xiàn)的接口
count(Countable $obj)返回是類內部的count()返回的結果,其會被強制轉成int
$arr = array( array("name" => "name value", "id" => 2), array("name" => "Peter", "id" => 4, "age" => 22), ); echo count($arr); echo count($arr[1]); class CountMe implements Countable { protected $myCount = 6; protected $myCount2 = 3; protected $myCount3 = 2; public function count() { // TODO: Implement count() method. return $this->myCount; } } $obj = new CountMe(); echo count($obj); //64.3 OuterIterator
?????OuterIterator接口
如果想對迭代器進行一定得處理湖再返回,可以用這個接口
IteratorIterator類是OuterIterator的實現(xiàn),擴展的時候,可以直接繼承IteratorIterator
$array = ["Value1","Value2","Value3","Value4"]; $outerObj = new OuterImpl(new ArrayIterator($array)); foreach ($outerObj as $key => $value){ echo "++".$key."-".$value." "; } class OuterImpl extends IteratorIterator { public function current() { return parent::current()."_tail"; } public function key() { return "Pre_".parent::key(); } }
++Pre_0-Value1_tail ++Pre_1-Value2_tail ++Pre_2-Value3_tail ++Pre_3-Value4_tail4.4 RecursiveIterator和SeekableIterator
?????
?????
完!
參考教程:站在巨人的肩膀上寫代碼—SPL
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/28632.html
摘要:什么是是標準庫的縮寫。根據(jù)官方定義,它是是用于解決典型問題的一組接口與類的集合。而的對象則嚴格以堆棧的形式描述數(shù)據(jù),并提供對應的方法。返回所有已注冊的函數(shù)。 什么是SPL SPL是Standard PHP Library(PHP標準庫)的縮寫。 根據(jù)官方定義,它是a collection of interfaces and classes that are meant to solve...
摘要:我把分為五個部分,,,,而其中是就是做一些類的介紹與相關的類在各自文章內,在介紹這些類之前,先介紹幾個接口數(shù)組式訪問接口只要實現(xiàn)了這個接口,就可以使得像那樣操作。只有內部的類用寫的類才可以直接實現(xiàn)接口代碼中使用或接口來實現(xiàn)遍歷。 我把SPL分為五個部分:Iterator,Classes,Exceptions,Datastructures,F(xiàn)unction;而其中classes是就是做一...
摘要:中在基礎集合類路由類中和分頁類中等,都用到了對象遍歷這個小知識點,這些類都是實現(xiàn)了這個接口,這個接口定義,返回的是迭代器對象。標準擴展庫中提供了很多默認迭代器實現(xiàn)類,比較常用的是數(shù)組迭代器對象,參考官網(wǎng)迭代器。 說明:本文章主要講述PHP的對象遍歷(Iterator)知識點。由于Laravel框架中就在集合(Collection)中用到了對象遍歷知識點,故記錄并學習之。同時,作者會將開...
摘要:也就是閑時為了寫文章而寫的一篇關于源碼的閱讀筆記。是標準庫的縮寫,一組旨在解決標準問題的接口和類的集合。提供了一套標準的數(shù)據(jù)結構,一組遍歷對象的迭代器,一組接口,一組標準的異常,一系列用于處理文件的類,提供了一組函數(shù),具體可以查看文檔。 也就是閑時為了寫文章而寫的一篇關于 Pimple 源碼的閱讀筆記。Pimple 代碼有兩種編碼方式,一種是以 PHP 編寫的,另一種是以 C 擴展編寫...
摘要:由于沒有方法,所以就不能用重置游標,這個時候已經到最后了,所以為空一種占位符形式的迭代器,不執(zhí)行任何操作。檢查是否含有子節(jié)點輸出所有字節(jié)點將一個樹形結構的迭代器展開為一維結構。 Iterator界面 本段內容來自阮一峰老師再加自己的部分注解 SPL規(guī)定,所有部署了Iterator界面的class,都可以用在foreach Loop中。Iterator界面中包含5個必須部署的方法: * ...
閱讀 3558·2021-11-08 13:15
閱讀 2115·2019-08-30 14:20
閱讀 1396·2019-08-28 18:08
閱讀 989·2019-08-28 17:51
閱讀 1496·2019-08-26 18:26
閱讀 2998·2019-08-26 13:56
閱讀 1494·2019-08-26 11:46
閱讀 2594·2019-08-23 14:22