深入理解PHP中的Iterable介面

一、什麼是Iterable介面

Iterable介面是PHP 7.1中新增加的一個介面,用來表示一個類是否能夠被迭代。一個類只要實現了Iterator或者IteratorAggregate介面,就可以被foreach迭代。

實現Iterator介面需要實現以下4個方法:

	class MyIterator implements Iterator {
	    private $items = [];
	    private $currentIndex = 0;
	
	    public function __construct(array $items) {
	        $this->items = $items;
	    }
	
	    public function rewind() {
	        $this->currentIndex = 0;
	    }
	
	    public function current() {
	        return $this->items[$this->currentIndex];
	    }
	
	    public function key() {
	        return $this->currentIndex;
	    }
	
	    public function next() {
	        $this->currentIndex++;
	    }
	
	    public function valid() {
	        return isset($this->items[$this->currentIndex]);
	    }
	}

實現IteratorAggregate介面需要實現一個getIterator方法,返回一個實現了Iterator介面的對象,例如:

	class MyIterable implements IteratorAggregate {
	    private $items = [];
	
	    public function __construct(array $items) {
	        $this->items = $items;
	    }
	
	    public function getIterator() {
	        return new MyIterator($this->items);
	    }
	}

二、Iterable介面的作用

Iterable介面的作用是可以讓我們自定義的數據結構通過foreach語法進行遍歷。

例如下面這個例子,我們可以實現一個自定義的鏈表數據結構,並使用foreach語法遍歷鏈表:

	class ListNode {
	    public $val = 0;
	    public $next = null;
	
	    public function __construct($val) {
	        $this->val = $val;
	    }
	}
	
	class LinkedList implements IteratorAggregate {
	    public $head = null;
	    public $tail = null;
	    public $count = 0;
	
	    public function add($node) {
	        if ($this->head == null) {
	            $this->head = $node;
	            $this->tail = $node;
	        } else {
	            $this->tail->next = $node;
	            $this->tail = $node;
	        }
	        $this->count++;
	    }
	
	    public function getIterator() {
	        $node = $this->head;
	        while ($node) {
	            yield $node;
	            $node = $node->next;
	        }
	    }
	}
	
	$list = new LinkedList();
	$list->add(new ListNode(1));
	$list->add(new ListNode(2));
	$list->add(new ListNode(3));
	
	foreach ($list as $node) {
	    echo $node->val . " ";
	}
	// output: 1 2 3

通過實現IteratorAggregate介面,並使getIterator方法返回一個生成器,就可以實現在自定義的鏈表數據結構上使用foreach語法遍歷。

三、Iterable介面的注意事項

在實現IteratorAggregate介面時,如果返回的Iterator沒有實現Rewindable介面,那麼鍵為0的元素不會被遍歷。

例如下面的例子:

	class MyIterator implements Iterator {
	    private $count = 3;
	    private $currentIndex = 0;
	
	    public function rewind() {
	        $this->currentIndex = 0;
	    }
	
	    public function current() {
	        return $this->currentIndex;
	    }
	
	    public function key() {
	        return $this->currentIndex;
	    }
	
	    public function next() {
	        $this->currentIndex++;
	        $this->count--;
	    }
	
	    public function valid() {
	        return $this->count > 0;
	    }
	}
	
	class MyIterable implements IteratorAggregate {
	    public function getIterator() {
	        return new MyIterator();
	    }
	}
	
	$iterable = new MyIterable();
	foreach ($iterable as $key => $value) {
	    echo "{$key} => {$value}\n";
	}
	// 輸出為1 => 1, 2 => 2

在這個例子中,$key為0的元素並沒有被遍歷,這是因為MyIterator沒有實現Rewindable介面。如果要使所有元素都被遍歷,需要在MyIterator中實現rewind方法。

四、Iterable介面的擴展

除了Iterator和IteratorAggregate介面,PHP還提供了Generator介面,它讓我們可以在調用生成器函數時,使用foreach語法一樣地對生成器提供迭代器。同時,Generator方法可以實現中斷和恢復執行的能力,可以用於處理大量數據進行分批次處理。

以數據分塊為例,下面是處理csv文件時,使用Generator實現文件分塊處理的一個例子:

	function readData($filename, $blockSize) {
	    if (!$handle = fopen($filename, 'r')) {
	        throw new InvalidArgumentException("Cannot open file ($filename)");
	    }
	
	    $lineCount = 0;
	    $block = "";
	    while (!feof($handle)) {
	        $line = fgets($handle);
	        $block .= $line;
	        $lineCount++;
	        if ($lineCount >= $blockSize) {
	            $lineCount = 0;
	            yield $block;
	            $block = "";
	        }
	    }
	
	    if (!empty($block)) {
	        yield $block;
	    }
	    fclose($handle);
	}
	
	$filename = "large.csv";
	$blockSize = 1000;
	foreach (readData($filename, $blockSize) as $block) {
	    // process each block of data
	}

此處是一個基於Generator實現的分塊處理csv文件的例子,可以使用foreach語法一樣地對生成器提供迭代器,同時也支持生成器的中斷和恢復執行的能力,可以用於處理大量數據進行分批次處理。

五、總結

Iterable介面是PHP 7.1新增的一個介面,使用Iterable介面可以實現自定義的數據結構在遍歷時使用foreach語法。通過實現Iterator或IteratorAggregate介面,並使getIterator方法返回一個可迭代的對象,就可以在自定義的數據結構上使用foreach語法。

除了Iterator和IteratorAggregate介面,PHP還提供了Generator介面,可以在調用生成器函數時,使用foreach語法一樣地對生成器提供迭代器。Generator方法可以實現中斷和恢復執行的能力,可以用於處理大量數據進行分塊處理。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/200971.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-06 11:29
下一篇 2024-12-06 11:29

相關推薦

  • PHP和Python哪個好找工作?

    PHP和Python都是非常流行的編程語言,它們被廣泛應用於不同領域的開發中。但是,在考慮擇業方向的時候,很多人都會有一個問題:PHP和Python哪個好找工作?這篇文章將從多個方…

    編程 2025-04-29
  • PHP怎麼接幣

    想要在自己的網站或應用中接受比特幣等加密貨幣的支付,就需要對該加密貨幣擁有一定的了解,並使用對應的API進行開發。本文將從多個方面詳細闡述如何使用PHP接受加密貨幣的支付。 一、環…

    編程 2025-04-29
  • Java 監控介面返回信息報錯信息怎麼處理

    本文將從多個方面對 Java 監控介面返回信息報錯信息的處理方法進行詳細的闡述,其中包括如何捕獲異常、如何使用日誌輸出錯誤信息、以及如何通過異常處理機制解決報錯問題等等。以下是詳細…

    編程 2025-04-29
  • 使用PHP foreach遍歷有相同屬性的值

    本篇文章將介紹如何使用PHP foreach遍歷具有相同屬性的值,並給出相應的代碼示例。 一、基礎概念 在講解如何使用PHP foreach遍歷有相同屬性的值之前,我們需要先了解幾…

    編程 2025-04-28
  • Python介面自動化測試

    本文將從如下多個方面對Python編寫介面自動化進行詳細闡述,包括基本介紹、常用工具、測試框架、常見問題及解決方法 一、基本介紹 介面自動化測試是軟體測試中的一種自動化測試方式。通…

    編程 2025-04-27
  • PHP獲取301跳轉後的地址

    本文將為大家介紹如何使用PHP獲取301跳轉後的地址。301重定向是什麼呢?當我們訪問一個網頁A,但是它已經被遷移到了另一個地址B,此時若伺服器端做了301重定向,那麼你的瀏覽器在…

    編程 2025-04-27
  • Jadoor門鎖開發介面接入指南

    本文將從多個方面詳細介紹如何將門鎖接入Jadoor平台的開發介面,方便開發者們快速實現門鎖遠程控制、開鎖記錄查看等功能。 一、Jadoor門鎖開發介面簡介 Jadoor是一款用於密…

    編程 2025-04-27
  • 後端介面設計開發經驗分享

    在受到前端某些限制或特殊需求時,後端介面的設計和開發顯得尤為重要。下面從以下幾個方面進行講述。 一、命名規範 合理的命名規範可以大大提高介面的可讀性和可維護性。以下是一些命名規範的…

    編程 2025-04-27
  • PHP登錄頁面代碼實現

    本文將從多個方面詳細闡述如何使用PHP編寫一個簡單的登錄頁面。 1. PHP登錄頁面基本架構 在PHP登錄頁面中,需要包含HTML表單,用戶在表單中輸入賬號密碼等信息,提交表單後服…

    編程 2025-04-27
  • 期貨數據介面 Python:打通數字資產交易數據的關鍵

    本文將從以下幾個方面討論期貨數據介面 Python: 一、數據介面簡介 期貨數據介面是指為期貨從業人員提供用於獲取歷史、實時及未來交易數據的工具。Python是一種常用的編程語言,…

    編程 2025-04-27

發表回復

登錄後才能評論