什么是SPLphp
S
tandard P
HP L
ibrarySPL: 用于解决常见广泛问题的一组接口与类的集合数组
Common Problem:数据结构
数学建模/数据结构app
元素遍历框架
经常使用方法的统一调用函数
类定义的自动装载工具
SPL的基本框架this
Bottom:最早添加到链表中的节点叫作Bottom
(底部),也称为头部(head
)
Top:最后添加到链表中得节点叫作top
顶部,也称为尾部
链表指针:是一个当前关注的节点的标识,能够指向任意节点
当前指针:链表指针指向的节点称为当前节点
节点名称:能够在链表中惟一标识一个节点的名称,咱们一般又称为节点的key
或offset
节点数据:存放在链表中的应用数据,一般称为value
spa
/** * 双向链表 */ $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
)中追加节点
Pop: 把top
位置的节点从链表中删除,操做不改变当前指针的位置
Unshif: 往链表底部追加节点(Bottom
)
Shif: 删除链表底部的节点
Rewind: 把节点指针指向Bottom
所在的节点
Current: 指向链表当前节点的指针,必须
在调用以前先调用rewind
。当指向的节点被删除以后,会指向一个空节点
Next: 指针指向下一个节点,current
的返回值随之改变
Prev: 指针指向上一个节点,current
的返回值随之改变3d
双向链表判断当前节点是否有效节点方法:
if(双向链表对象.current()) 有效 else 无效
或
//用$obj->current()判断当前是否有迭代元素很差,由于当元素值是false,0,或者空字符时 //他们效果和null同样,区分不了,因此严谨的话要使用valid方法判断 if(双向链表对象.valid()) 有效 else 无效
继承自SplDoublyLinkedList类的SplStack类
操做:
- `push`:压入堆栈(存入) - `pop`:退出堆栈(取出)
堆栈:单端出入,先进后出 Fist In Last Out(FILO
)
/** * 堆栈 */ $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`方法,方向相反
队列和堆栈恰好相反,最早进入队列的元素会最早走出队列
继承自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: 插入一个节点到队列里面的top
位置
dequeue: 操做从队列中提取Bottom
位置的节点,同时从队列里面删除该元素
offSet(0): 是Bottom
所在的位置
rewind: 操做使得指针指向Bottom
所在的位置的节点
next: 操做使得当前指针指向Top
方向的下一个节点
经过某种
统一的方式
遍历链表或则数组中的元素的过程叫作迭代遍历,这种统一的遍历工具叫迭代器
PHP
中迭代器是经过Iterator
接口定义的
ArrayIterator
迭代器用于遍历数组
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();//生成数组的迭代器。 foreach ($it as $key => $value){ echo $key . ":". $value .'<br />'; } echo '<br />'; //实现和foreach一样功能 $it->rewind();// 调用current以前必定要调用rewind While($it->valid()){//判断当前是否为有效数据 echo $it->key().' : '.$it->current().'<br />'; $it->next();//千万不能少 } //实现更复杂功能,跳过某些元素进行打印 $it->rewind(); if ($it->valid()){ $it->seek(1);//position,跳过前面 n-1的元素 While($it->valid()){//判断当前是否为有效数据 echo $it->key().' : '.$it->current().'<br />'; $it->next();//千万不能少 } } $it->ksort();//对key进行字典序排序 //$it->asort();//对值进行字典序排序 foreach ($it as $key => $value){ echo $key . ":". $value .'<br />'; }
foreach
本质会自动生成一个迭代器,只是使用了迭代器的最长用功能,若是要实现复杂需求,foreach
实现不了,就须要手动生成迭代器对象来使用了
好比,要从一个大数组中取出一部分数据,foreach
比较困难,除非他知道数据的样子。将数组或者集合中的所有或者一部数据取出来,用迭代器比较方便
AppendIterator
能陆续遍历几个迭代器
$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);//追加数组 $it->append($arr_b);//追加数组,而后遍历$it foreach ($it as $key => $value){ print_r($value); }
用于把多个Iterator
里面的数据组合成为一个总体来访问
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关联 $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 )
filesystemIterator
seek
方法定位到集合里面的某个特定元素 在代码里面常常能够直接用count($obj)
方法获取对象里面的元素个数
count(array('name'=>'Peter','id'=>'5'));
对于咱们定义的类,也能这样访问吗?
count
函数,可是没有继承countable
接口,直接用count
函数时,不会调用对象自定义的count
若是对象自己也有count
函数,同时对象也继承了countable
接口,直接用count
函数时,会调用对象自身的count
函数,效果至关与:对象->count()
count()
是Countable
必须实现的接口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); //6
OuterIterator接口
IteratorIterator
类是OuterIterator
的实现,扩展的时候,能够直接继承IteratorIterator
$array = ['Value1','Value2','Value3','Value4']; $outerObj = new OuterImpl(new ArrayIterator($array)); foreach ($outerObj as $key => $value){ echo "++".$key.'-'.$value."\n"; } 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_tail
完!