列表推導式

列表推導式（list comprehension），是程序設計語言的一類語法結構，用於基於描述創建一個列表（list）數據結構。相當於數學上的集合建構式符號。但不同於map與filter函數。
“list comprehension”沒有統一的中文譯法。有譯作列表解析式、列表生成式、列表構建、列表理解等。

**概述**
考慮下述集合建構式符號：

可讀作：“是所有“乘”的數的集合，滿足是自然數，並且的平方大於。”
-  是表示輸入集合的成員的變量。-  表示輸入集合，這裡是自然數。-  是謂詞表示式，用於從輸入集篩選。-  是輸出表達式，用於產生新的集合。 -  花括號表示輸出值組成集合。-  豎槓讀作“滿足”，可以同冒號“:”互換使用。-  逗號分隔謂詞，可以讀作“並且”。
列表推導式，與從一個輸入列表或迭代器，依次生成一個列表的表示，有相同的語法構件：- 代表輸入列表的成員的一個變量。- 一個輸入列表（或迭代器）。- 一個可選的謂詞（判斷）表達式。- 和從滿足這個判斷的，輸入可迭代者的成員，產生輸出列表的成員的一個表達式。
在Haskell的列表推導式語法中，上述集合建造結構類似的寫為如下：
s =  x  3 
這裡的列表0..表示，x^2 > 3表示謂詞，而2*x表示輸出表達式。列表推導式，按一個確定次序，給出結果（不同於集合的成員）；並且列表推導式，可以依次生成一個列表的成員，而非生成這個列表的全體，從而允許前面的對一個無窮列表的成員的Haskell定義。

**歷史**
在術語“列表推導式”使用之前，就存在了有關的構造。集合論編程語言SETL（1969年），有類似列表推導式的一種形成構造。比如，這個代碼打印從2到N的所有素數：
print(n in 2..N | forall m in {2..n - 1} | n mod m > 0);
計算機代數系統AXIOM（1973年），有處理串流的類似構造。
首次對這種構造的使用術語“推導式”，是在1977年以後，Rod Burstall和John Darlington，用在他們的函數式編程語言NPL的描述之中。在David Turner的回憶錄《函數式編程語言的一些歷史》中，他回想起：
NPL由Burstall用POP2實現，並被Darlington用於程序變換的工作（Burstall & Darlington 1977）。這個語言，是一階、強類型（但不多態）、純函數式、傳值調用的。它還有“集合表達式”比如：
setofeven (X)  
在給術語“列表推導式”附加的腳註中，Turner還記述了：
我最初稱其為“ZF表達式”，參照了Zermelo-Frankel集合論，Phil Wadler鑄就了更好的術語“列表推導式”。
Burstall和Darlington關於NPL的工作，在1980年代影響了很多函數式編程語言，但並非全部都包括了列表推導式。其中最有影響的，是1985年發行的，Turner的惰性純函數式編程語言Miranda。後來開發的標準惰性純函數式語言Haskell，包含了Miranda的很多特徵，包括列表推導式。

**Python示例**
Python語言的列表推導式和生成器表達式的語法示例：
>>> s = 2*x for x in range(10) if x**2 > 3
>>> print(s)
4, 6, 8, 10, 12, 14, 16, 18
>>> from itertools import count, islice
>>> s = (2*x for x in count(0) if x**2 > 3)
>>> t = islice(s, 10)
>>> print(*t)
4, 6, 8, 10, 12, 14, 16, 18, 20, 22
>>> print(*t)
>>> t = islice(s,10)
>>> print(*t)
24, 26, 28, 30, 32, 34, 36, 38, 40, 42

**推廣**

**並行列表推導式=== 
格拉斯哥Haskell編譯器，擁有一個擴展叫作“並行列表推導式”（也叫做拉鍊推導式），它允許在列表推導式語法中，有多個獨立分支的限定符。用逗號,分隔的限定符，是依賴的（“嵌套的”）；而用管道符號|分隔的限定符，是並行求值的（這不涉及任何形式的多線程性，這隻意味著這些分支是被拉鍊合併的）。
-- 常規列表推導式
a = (x,y) | x 
Python語言的語法示例： 
# 常規列表推導式
>>> (x, y) for x in range(1, 6) for y in range(6, 9)
(1, 6), (1, 7), (1, 8), (2, 6), (2, 7), (2, 8), (3, 6), (3, 7), (3, 8), (4, 6), (4, 7), (4, 8), (5, 6), (5, 7), (5, 8)
# 並行/拉鍊列表推導式
>>> s = zip(range(1, 6), range(6, 9))
>>> t = x for x in s
>>> print(t)
(1, 6), (2, 7), (3, 8)
>>> from operator import add
>>> *map(add, range(1, 6), range(6, 9)) # 有二個實際參數列表的map相當於Haskell的zipWith
7, 9, 11
>>> from itertools import starmap, zip_longest
>>> *starmap(add, t)
7, 9, 11
>>> s = zip_longest(range(1, 6), range(6, 9))
>>> t = *s
>>> print(t)
(1, 6), (2, 7), (3, 8), (4, None), (5, None)
>>> *zip(*t)
(1, 2, 3, 4, 5), (6, 7, 8, None, None)

**單子推導式**
在Haskell中，單子推導式將列表推導式，推廣為適用於任何單子。

**集合推導式**
Python語言用於生成集合的語法示例：
>>> s = {v for v in 'ABCDABCD' if v not in 'CB'}
>>> print(s)
{'A', 'D'}

**字典推導式**
Python語言用於生成字典（關聯數組）的語法示例： 
>>> s = {key: val for key, val in enumerate('ABCD') if val not in 'CB'}
>>> print(s)
{0: 'A', 3: 'D'}

**類似構造**

**C++**
C++沒有直接支持列表推導的任何語言特性，但運算符重載（例如，重載|，>>，>> =）已成功用於為“嵌入式”查詢領域特定語言提供表達式語法。 或者，可以使用erase–remove慣用法來構造列表推導以選擇容器中的元素，並使用STL算法for_each來轉換它們。
#include 
#include 
#include 
using namespace std;
template
C comprehend(C&& source, const P& predicate, const T& transformation)
{
// 初始化目標
C d = forward(source);
// 元素過濾
d.erase(remove_if(begin(d), end(d), predicate), end(d));
// 應用變換
for_each(begin(d), end(d), transformation);
return d;
}
int main()
{
list range(10);  
// range 是一個有10個元素的list, 全是0
iota(begin(range), end(range), 1);
// range 現在包含 1,2,...,10
list result = comprehend(
range,
(int x){return x*x 

**參見**
Comparison of programming languages (list comprehension)

**延伸閱讀**
List Comprehension in The Free On-line Dictionary of Computing, Editor Denis Howe.- year = 1992- archive-url = https://web.archive.org/web/20201111215332/http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.33.5381 - year = 2000
Haskell
*The Haskell 98 Report, chapter 3.11 List Comprehensions.
*The Glorious Glasgow Haskell Compilation System User's Guide, chapter 7.3.4 Parallel List Comprehensions.
*The Hugs 98 User's Guide, chapter 5.1.2 Parallel list comprehensions (a.k.a. zip-comprehensions).
OCaml- OCaml Batteries Included.- Language extensions introduced in OCaml Batteries Included.
Python- The Python Tutorial, List Comprehensions.- Python Language Reference, List displays.- Python Enhancement Proposal PEP 202: List Comprehensions.- Python Language Reference, Generator expressions.- Python Enhancement Proposal PEP 289: Generator Expressions.
Common Lisp- Implementation of a Lisp comprehension macro by Guy Lapalme.
Clojure- Clojure API documentation - for macro.
Axiom- Axiom stream examples.

**參考文獻**

**外部鏈接**
 SQL-like set operations with list comprehension one-liners in the  Python Cookbookdate=20080702210432 -  Discussion on list comprehensions in Scheme and related constructs date=20200728004619 -  List Comprehensions across languages date=20201109035921