2009-09-13 71 views
15

我在Python中使用列表理解語法時遇到了一些麻煩,所以我開始考慮如何在Perl中實現同樣的功能,這是我更熟悉的。我意識到基本示例(取自this page)都可以在Perl中用mapgrep完成。Perl列表解析是否與Perl中的map/grep相同?

E.g.

(python)       (perl)     
S = [x**2 for x in range(10)]  @S = map { $_**2 } (0..9); 
V = [2**i for i in range(13)]  @V = map { 2**$_ } (0..12); 
M = [x for x in S if x % 2 == 0] @M = grep { $_ % 2 == 0 } @S; 

所以是「列表理解」只是看中術語「映射和/或篩選列表」或者有更多的嗎?

回答

13

你是對的:列表理解本質上只是語法糖,用於映射和過濾(來自函數式編程世界的術語)。

希望這個代碼示例演示了他們的平等:

>>> # Python 2 
>>> [x**2 for x in range(10)] == map(lambda x: x**2, range(10)) 
True 
>>> [2**i for i in range(13)] == map(lambda x: 2**x, range(13)) 
True 
>>> S = [x**2 for x in range(10)] 
>>> [x for x in S if x % 2 == 0] == filter(lambda x: x % 2 == 0, S) 
True 

注意,這是唯一有效的在Python 2.X,如SilentGhost在評論中指出。爲了使其與Python 3兼容,您必須將調用包裝到list構造函數中進行映射或過濾,因爲映射和過濾器已更新爲返回迭代器而不是列表。因爲它們允許你抽象與列表播放

>>> # Python 3 
>>> [x**2 for x in range(10)] == list(map(lambda x: x**2, range(10))) 
True 
>>> [2**i for i in range(13)] == list(map(lambda x: 2**x, range(13))) 
True 
>>> S = [x**2 for x in range(10)] 
>>> [x for x in S if x % 2 == 0] == list(filter(lambda x: x % 2 == 0, S)) 
True 
+0

只適用於py2k。 – SilentGhost 2009-09-13 21:47:48

0

列表理解比地圖或過濾器更強大。

當你的地圖與更多地圖和過濾器調用進一步嵌套時,使用它們也更方便。

+2

你能舉一個例子說明你的意思是「抽象地使用列表嗎?」 – friedo 2009-09-13 21:50:16

3

是的,它們基本上是一樣的。

事實上Python中也有一個地圖功能:

S = map(lambda x: x**2, range(10)) 

是一樣的上述第一個例子。但是,Python中強烈首選列表解析語法。我相信圭多被引述說他遺憾地引入了函數式語法。

然而,它真正有趣的地方在於列表解析的下一個演變,它是生成器。這些允許你返回一個迭代器 - 而不是一次處理整個列表,它只執行一次迭代,然後返回,所以你不必同時把整個列表保存在內存中。很強大。

+0

我認爲它是一個生成器本質上是其他語言稱爲迭代器的東西? – friedo 2009-09-13 22:17:09

+1

@friedo迭代器是一種模式,生成器是一種實現該模式的方式 – fortran 2009-09-13 22:20:24

0

是的。 Python語法的強大之處在於,也使用相同的語法(在圓括號內而不是方括號內)來定義生成器,這些生成器按需生成值序列。

2

他們的「Python化」版本映射和過濾序列,但他們允許做一些其他的事情,比如壓扁(固定級)嵌套列表,例如:

[j for i in nested_list for j in i] 

另一件事,你不能做一個普通地圖和Lambda表達式是結構分解迭代值,例如:

[(x%y)*z for x,y,z in list_with_triplets_of_ints] 
當然

有喜歡的解決方法:

aux = lambda x,y,z: (x%y)*z 
map(lambda t: aux(*t), list_with_triplets_of_ints) 

但是當你需要應用的轉變已經定義的話,通常它只是簡單的使用地圖,像:

map(int, list_of_str_values) 

而不是

[int(i) for i in list_of_str_values] 
+0

+1謝謝。我特別喜歡三胞胎的例子;這很難與地圖簡潔地完成。 – friedo 2009-09-13 22:34:42

2

列表理解也展平東西:

例如:

x(x,y)對於xrange(10)x如果x%2 == 0對於yrange(20)如果x!= y]

如果您在此處使用嵌套映射,則必須也可以使用concat(彙總列表)。