摘要:將數(shù)組或者集合中的全部或者一部數(shù)據(jù)取出來,用迭代器比較方便迭代器能陸續(xù)遍歷幾個(gè)迭代器按順序迭代訪問幾個(gè)不同的迭代器。
一、SPL簡(jiǎn)介
?????什么是SPL
PHP的標(biāo)準(zhǔn)庫(kù)SPL:Standard PHP Library
?????SPL: 用于解決常見普遍問題的一組接口與類的集合
?????Common Problem:
數(shù)學(xué)建模/數(shù)據(jù)結(jié)構(gòu)
解決數(shù)據(jù)怎么存儲(chǔ)的問題
元素遍歷
數(shù)據(jù)怎么查看問題
常用方法的統(tǒng)一調(diào)用
通用方法(數(shù)組、集合的大小)
自定義遍歷
類定義的自動(dòng)裝載
讓PHP程序適應(yīng)大型項(xiàng)目的管理要求,把功能的實(shí)現(xiàn)分散到不同的文件中
?????SPL的基本框架
?????
二、SPL的常用數(shù)據(jù)結(jié)構(gòu)?????
2.1 雙向鏈表 2.1.1 雙向鏈表簡(jiǎn)介?????
?????Bottom:最先添加到鏈表中的節(jié)點(diǎn)叫做Bottom(底部),也稱為頭部(head)
?????Top:最后添加到鏈表中得節(jié)點(diǎn)叫做top頂部,也稱為尾部
?????鏈表指針:是一個(gè)當(dāng)前關(guān)注的節(jié)點(diǎn)的標(biāo)識(shí),可以指向任意節(jié)點(diǎn)
?????當(dāng)前指針:鏈表指針指向的節(jié)點(diǎn)稱為當(dāng)前節(jié)點(diǎn)
?????節(jié)點(diǎn)名稱:可以在鏈表中唯一標(biāo)識(shí)一個(gè)節(jié)點(diǎn)的名稱,我們通常又稱為節(jié)點(diǎn)的key或offset
?????節(jié)點(diǎn)數(shù)據(jù):存放在鏈表中的應(yīng)用數(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: 獲得鏈表底部(頭部)元素,當(dāng)前指針位置不變
?????Top: 獲取鏈表頂部(尾部)元素,當(dāng)前指針位置不變
?????Push: 往鏈表頂部(Top)中追加節(jié)點(diǎn)
?????Pop: 把top位置的節(jié)點(diǎn)從鏈表中刪除,操作不改變當(dāng)前指針的位置
?????Unshif: 往鏈表底部追加節(jié)點(diǎn)(Bottom)
?????Shif: 刪除鏈表底部的節(jié)點(diǎn)
?????Rewind: 把節(jié)點(diǎn)指針指向Bottom所在的節(jié)點(diǎn)
?????Current: 指向鏈表當(dāng)前節(jié)點(diǎn)的指針,必須在調(diào)用之前先調(diào)用rewind。當(dāng)指向的節(jié)點(diǎn)被刪除之后,會(huì)指向一個(gè)空節(jié)點(diǎn)
?????Next: 指針指向下一個(gè)節(jié)點(diǎn),current的返回值隨之改變
?????Prev: 指針指向上一個(gè)節(jié)點(diǎn),current的返回值隨之改變
?????雙向鏈表判斷當(dāng)前節(jié)點(diǎn)是否有效節(jié)點(diǎn)方法:
if(雙向鏈表對(duì)象.current()) 有效 else 無效
?????或
//用$obj->current()判斷當(dāng)前是否有迭代元素不好,因?yàn)楫?dāng)元素值是false,0,或者空字符時(shí) //他們效果和null一樣,區(qū)分不了,所以嚴(yán)謹(jǐn)?shù)脑捯褂胿alid方法判斷 if(雙向鏈表對(duì)象.valid()) 有效 else 無效2.2 堆棧 2.2.1 堆棧簡(jiǎn)介
?????繼承自SplDoublyLinkedList類的SplStack類
?????操作:
- `push`:壓入堆棧(存入) - `pop`:退出堆棧(取出)
?????堆棧:?jiǎn)味顺鋈耄冗M(jìn)后出 Fist In Last Out(FILO)
2.2.2 堆棧代碼實(shí)踐/** * 堆棧 */ $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(): 最先進(jìn)入的元素;
?????Top(): 最后進(jìn)入的元素;
?????offSet(0): 是top的位置
?????rewind(): 把top的元素置為current()的位置
?????注意:
- 堆棧的`rewind()`指向`top`,雙向鏈表的`rewind()`指向`bottom` - 堆棧和雙向鏈表都有`next`方法,方向相反2.3 隊(duì)列
?????隊(duì)列和堆棧剛好相反,最先進(jìn)入隊(duì)列的元素會(huì)最先走出隊(duì)列
?????繼承自SplDoublyLinkedList類的SqlQueue類
?????操作:
- `enqueue`:進(jìn)入隊(duì)列 - `dequeue`:退出隊(duì)列
/** * 隊(duì)列 */ $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: 插入一個(gè)節(jié)點(diǎn)到隊(duì)列里面的top位置
?????dequeue: 操作從隊(duì)列中提取Bottom位置的節(jié)點(diǎn),同時(shí)從隊(duì)列里面刪除該元素
?????offSet(0): 是Bottom所在的位置
?????rewind: 操作使得指針指向Bottom所在的位置的節(jié)點(diǎn)
?????next: 操作使得當(dāng)前指針指向Top方向的下一個(gè)節(jié)點(diǎn)
通過某種 統(tǒng)一的方式 遍歷鏈表或則數(shù)組中的元素的過程叫做迭代遍歷,這種統(tǒng)一的遍歷工具叫迭代器
?????PHP中迭代器是通過Iterator接口定義的
3.2 ArrayIterator迭代器?????ArrayIterator迭代器用于遍歷數(shù)組
seek(),指針定位到某個(gè)位置,很實(shí)用,跳過前面n-1的元素
ksort(),對(duì)key進(jìn)行字典序排序
asort(),對(duì)值進(jìn)行字典序排序
$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 "
"; //實(shí)現(xiàn)和foreach同樣功能 $it->rewind();// 調(diào)用current之前一定要調(diào)用rewind While($it->valid()){//判斷當(dāng)前是否為有效數(shù)據(jù) echo $it->key()." : ".$it->current()."
"; $it->next();//千萬不能少 } //實(shí)現(xiàn)更復(fù)雜功能,跳過某些元素進(jìn)行打印 $it->rewind(); if ($it->valid()){ $it->seek(1);//position,跳過前面 n-1的元素 While($it->valid()){//判斷當(dāng)前是否為有效數(shù)據(jù) echo $it->key()." : ".$it->current()."
"; $it->next();//千萬不能少 } } $it->ksort();//對(duì)key進(jìn)行字典序排序 //$it->asort();//對(duì)值進(jìn)行字典序排序 foreach ($it as $key => $value){ echo $key . ":". $value ."
"; }
?????foreach本質(zhì)會(huì)自動(dòng)生成一個(gè)迭代器,只是使用了迭代器的最長(zhǎng)用功能,如果要實(shí)現(xiàn)復(fù)雜需求,foreach實(shí)現(xiàn)不了,就需要手動(dòng)生成迭代器對(duì)象來使用了
?????比如,要從一個(gè)大數(shù)組中取出一部分?jǐn)?shù)據(jù),foreach比較困難,除非他知道數(shù)據(jù)的樣子。將數(shù)組或者集合中的全部或者一部數(shù)據(jù)取出來,用迭代器比較方便
?????AppendIterator能陸續(xù)遍歷幾個(gè)迭代器
按順序迭代訪問幾個(gè)不同的迭代器。例如,希望在一次循環(huán)中迭代訪問兩個(gè)或者更多的組合
$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迭代器
?????用于把多個(gè)Iterator里面的數(shù)據(jù)組合成為一個(gè)整體來訪問
Multipleiterator將多個(gè)arrayiterator拼湊起來
Appenditerator將多個(gè)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關(guān)聯(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的基礎(chǔ)接口 4.1 最常用的接口
Countable:繼承了該接口的類可以直接調(diào)用count(),得到元素個(gè)數(shù)
OuterIterator:,如果想對(duì)迭代器進(jìn)行一定的處理之后再返回,可以用這個(gè)接口,相當(dāng)于進(jìn)行了一次封裝,對(duì)原來的進(jìn)行一定的處理
RecursiveIterator:,可以對(duì)多層結(jié)構(gòu)的迭代器進(jìn)行迭代,比如遍歷一棵樹,類似于filesystemIterator
SeekableIterator:,可以通過seek方法定位到集合里面的某個(gè)特定元素
4.2 Countable?????在代碼里面經(jīng)常可以直接用count($obj)方法獲取對(duì)象里面的元素個(gè)數(shù)
count(array("name"=>"Peter","id"=>"5"));
?????對(duì)于我們定義的類,也能這樣訪問嗎?
如果對(duì)象本身也有count函數(shù),但是沒有繼承countable接口,直接用count函數(shù)時(shí),不會(huì)調(diào)用對(duì)象自定義的count
如果對(duì)象本身也有count函數(shù),同時(shí)對(duì)象也繼承了countable接口,直接用count函數(shù)時(shí),會(huì)調(diào)用對(duì)象自身的count函數(shù),效果相當(dāng)與:對(duì)象->count()
count()是Countable必須實(shí)現(xiàn)的接口
count(Countable $obj)返回是類內(nèi)部的count()返回的結(jié)果,其會(huì)被強(qiáng)制轉(zhuǎn)成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接口
如果想對(duì)迭代器進(jìn)行一定得處理湖再返回,可以用這個(gè)接口
IteratorIterator類是OuterIterator的實(shí)現(xiàn),擴(kuò)展的時(shí)候,可以直接繼承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
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/28632.html
摘要:什么是是標(biāo)準(zhǔn)庫(kù)的縮寫。根據(jù)官方定義,它是是用于解決典型問題的一組接口與類的集合。而的對(duì)象則嚴(yán)格以堆棧的形式描述數(shù)據(jù),并提供對(duì)應(yīng)的方法。返回所有已注冊(cè)的函數(shù)。 什么是SPL SPL是Standard PHP Library(PHP標(biāo)準(zhǔn)庫(kù))的縮寫。 根據(jù)官方定義,它是a collection of interfaces and classes that are meant to solve...
摘要:我把分為五個(gè)部分,,,,而其中是就是做一些類的介紹與相關(guān)的類在各自文章內(nèi),在介紹這些類之前,先介紹幾個(gè)接口數(shù)組式訪問接口只要實(shí)現(xiàn)了這個(gè)接口,就可以使得像那樣操作。只有內(nèi)部的類用寫的類才可以直接實(shí)現(xiàn)接口代碼中使用或接口來實(shí)現(xiàn)遍歷。 我把SPL分為五個(gè)部分:Iterator,Classes,Exceptions,Datastructures,F(xiàn)unction;而其中classes是就是做一...
摘要:中在基礎(chǔ)集合類路由類中和分頁(yè)類中等,都用到了對(duì)象遍歷這個(gè)小知識(shí)點(diǎn),這些類都是實(shí)現(xiàn)了這個(gè)接口,這個(gè)接口定義,返回的是迭代器對(duì)象。標(biāo)準(zhǔn)擴(kuò)展庫(kù)中提供了很多默認(rèn)迭代器實(shí)現(xiàn)類,比較常用的是數(shù)組迭代器對(duì)象,參考官網(wǎng)迭代器。 說明:本文章主要講述PHP的對(duì)象遍歷(Iterator)知識(shí)點(diǎn)。由于Laravel框架中就在集合(Collection)中用到了對(duì)象遍歷知識(shí)點(diǎn),故記錄并學(xué)習(xí)之。同時(shí),作者會(huì)將開...
摘要:也就是閑時(shí)為了寫文章而寫的一篇關(guān)于源碼的閱讀筆記。是標(biāo)準(zhǔn)庫(kù)的縮寫,一組旨在解決標(biāo)準(zhǔn)問題的接口和類的集合。提供了一套標(biāo)準(zhǔn)的數(shù)據(jù)結(jié)構(gòu),一組遍歷對(duì)象的迭代器,一組接口,一組標(biāo)準(zhǔn)的異常,一系列用于處理文件的類,提供了一組函數(shù),具體可以查看文檔。 也就是閑時(shí)為了寫文章而寫的一篇關(guān)于 Pimple 源碼的閱讀筆記。Pimple 代碼有兩種編碼方式,一種是以 PHP 編寫的,另一種是以 C 擴(kuò)展編寫...
摘要:由于沒有方法,所以就不能用重置游標(biāo),這個(gè)時(shí)候已經(jīng)到最后了,所以為空一種占位符形式的迭代器,不執(zhí)行任何操作。檢查是否含有子節(jié)點(diǎn)輸出所有字節(jié)點(diǎn)將一個(gè)樹形結(jié)構(gòu)的迭代器展開為一維結(jié)構(gòu)。 Iterator界面 本段內(nèi)容來自阮一峰老師再加自己的部分注解 SPL規(guī)定,所有部署了Iterator界面的class,都可以用在foreach Loop中。Iterator界面中包含5個(gè)必須部署的方法: * ...
閱讀 3553·2021-11-08 13:15
閱讀 2110·2019-08-30 14:20
閱讀 1393·2019-08-28 18:08
閱讀 983·2019-08-28 17:51
閱讀 1488·2019-08-26 18:26
閱讀 2992·2019-08-26 13:56
閱讀 1490·2019-08-26 11:46
閱讀 2590·2019-08-23 14:22