2011-06-06 118 views
21

我今天正在細讀手冊並注意到various iterators。對我來說,似乎他們都毫無意義;我沒有看到使用它們的理由,除非你更喜歡它們的語法,或者不知道如何編寫遞歸函數。是否有任何理由在PHP中使用內置迭代器而不是編寫循環或製作遞歸方法?我只是在尋找事實反應,而不是主觀偏好(即:我不在乎你是否認爲它更「可讀」或「更面向對象」,我想知道它們是否更快,提供滾動自己時無法實現的功能等)。PHP - 使用迭代器的原因?

+5

「更多面向對象」不是主觀意見;它深入研究問題的功能集。如果你處理對象,以面向對象的方式處理它們並不是主觀的。 – AlexanderJohannesen 2011-06-06 02:05:30

+0

我認爲在這種情況下,「更多面向對象」是一種主觀意見,因爲迭代器實現的實現並不比定製實現更「面向對象」。它們不再是面向對象的解決方案。 – mrjminer 2011-06-06 02:20:38

+1

這是一個奇怪的評論,因爲一些迭代器對傳統方法根本不起作用的特定對象進行操作(這是非常重要的一點)。除非將對象轉換爲數組,否則不能將對象視爲數組,除非經常這是不可能的;任何非樹形結構都會讓你頭痛不已。如果你依賴於某些關係的語義來遍歷一個圖,沒有迭代器這是不可能的,但通常是非常微不足道的。所以。不,不是非主觀的,除非你是伏爾泰並鑽研存在主義。 :) – AlexanderJohannesen 2011-06-06 02:28:52

回答

16

我相信主要原因是多功能性。他們不會讓事情更具可讀性,您可以通過簡單的foreach完成大部分spl iterators

但迭代器可以作爲一種可以傳遞的壓縮循環或循環源。您可以擁有更多不同的數據源,而不僅僅是一個列表/數組。真正的好處是你可以將它們進行包裝或堆疊以進行聚合。

命名有點不明顯,但我想你可以使用AppendIterator來例如結合一個靜態文件名列表和DirectoryIterator的結果。或以其他方式將其包裝在LimitIterator中,而不是將其硬編碼爲for條件。所有這些都是非常基本的功能,可以在foreach中手動完成。但至少RegexIteratorFilterIterator似乎適合降低一些複雜性。

但最終它確實是一種文體選擇。如果你有自定義對象遍歷某些東西(例如一個VFS對象,它可以指向真實文件或數據庫條目),這將是最有意義的。但即使如此,你可以只是iterator_to_array轉換這樣一個列表,並使用正常的foreach -over-array。

唯一的情況是,如果數據源的大小沒有限制,則首選迭代器是非常必要的。用於foreach的未摺疊數組可以消耗比可以逐元素檢索的迭代器更多的內存。

+0

我明白你的意思是無限大小的數據源。當我得到一些時間時,我將不得不測試內存/ CPU使用率。 – mrjminer 2011-06-06 02:17:52

+0

數組可以成爲「大小無限的數據源」嗎?如果不是,ArrayIterators有什麼意義? – Muc 2013-05-09 13:58:35

+0

@Muc數組不能。那些將他們的數據保存在內存中。但迭代器可以,因爲輸入可能是從文件/數據庫/套接字輸入/ urand等動態解析。 – mario 2013-05-09 14:10:23

7

一個簡單的例子:實現一個可以像數組一樣訪問和遍歷的對象。 SimpleXML是一個很好的例子,可以通過它實現強大的行爲。

要做到這一點,你可以implement定義方法public current()public key()public next()public rewind()public valid()Iterator interface

或者你可以簡單implement替代IteratorAggregate interface定義一個方法public getIterator()它只是返回要暴露內部數據的迭代器。

一定要看看上面的接口的例子,你會看到優勢。

+0

感謝您獲得SimpleXML的鏈接。我現在沒有時間去挖掘它,但快速查看發現它將是一個很好的例子。 – mrjminer 2011-06-06 02:26:23

+0

就是這樣的:你可以有一個對象_also_以及_other_功能。所以它適用於任何比複雜/高級更簡單的事情,而不僅僅是簡單地循環訪問一些簡單的數據結構。否則它只是膨脹,所以請記住KISS和YAGNI。 – DanMan 2016-09-16 09:49:46

7

該問題可以有各種各樣的答案,但適當的答案可能可以概括爲:迭代器可用於迭代比簡單數組更復雜的任何東西

一個例子是某種ORM或查詢生成器。假設我們有一個 - 用它可能看起來像:

$friends = new Model_Friend(); 
$friends = $people->where('age','>',30)->where('gender','=','female'); 
foreach ($friends as $friend) { 
    echo $friend->name; 
} 
1

迭代器一樣快,因爲別的,而是用更簡單的界面,或許更verbage把它包起來。然而,主要的優點是沒有什麼你現在可能需要,但如何擴展它們來處理你未來的問題(他們會來!),這就是我們老男孩所說的「拯救你未來的屁股」。 :)

13

迭代器的主要優點是它們抽象了迭代的概念。這意味着任何數據提供者都可以通過相同的接口使用。而這也正是在那裏,你可以把他們的優勢:

  • 懶惰
  • 減少內存使用
  • 組成

懶惰

與數據提供商,該數據僅取當你真的需要它時(例如,當你迭代時)。

減少內存使用

迭代鼓勵你反覆處理,而不是在內存中緩存數據它。雖然沒有迭代器可以做到這一點,但它們提供的抽象隱藏了實現,使得它們非常易於使用。

組成

什麼馬里奧說。


約扎斯Kaziukėnas最近寫的,他如何使用迭代器來模擬懶評價在PHP blog post。它詳細介紹了我提到的一些事情。