2015-12-11 68 views
1

我剛剛有一個想法,我覺得很有趣:map()和filter()之間的組合使用生成器作爲謂詞和yield from。爲了簡短起見,這裏是代碼:map()和filter()的組合

def map_filter(function, iterable): 
    """convert and filter a sequence""" 
    for i in iterable: 
     yield from function(i) 

現在,這是怎麼回事?基本上,這是上述兩個功能的組合,它們結合了它們的功能。實際上,將附加參數傳遞給map()的可能性仍然不存在,儘管這是一個小細節,恕我直言,它可以擴展。這裏有一個比較,數字生成平方:

def function(x): 
    return x * x 
res = map(function, range(0, 10)) 
print(list(res)) 

def function(x): 
    yield x * x 
res = map_filter(function, range(0, 10)) 
print(list(res)) 

下面是另一個,過濾奇數:

def function(x): 
    return x % 2 == 1 
res = filter(function, range(0, 10)) 
print(list(res)) 

def function(x): 
    if x % 2 == 1: 
     yield x 
res = map_filter(function, range(0, 10)) 
print(list(res)) 

,最後一個,結合上面的兩個:

def function1(x): 
    return x * x 
def function2(x): 
    return x % 2 == 1 
res = map(function1, filter(function2, range(0, 10))) 
print(list(res)) 

def function(x): 
    if x % 2 == 1: 
     yield x * x 
res = map_filter(function, range(0, 10)) 
print(list(res)) 

注意事項和問題:

  • 第一個問題當然,我是不是重新發明了輪子,或者這是Python的一個有用的補充(例如,在itertools)?
  • 這是否有任何問題或缺點?我看到的是一個稍微複雜的界面,但它似乎是一個用於一般序列操作的有用工具。
  • map_filter()需要一個發電機(與yield),所以我不能使用lambda(我可以嗎?)。對於非常小的過濾/映射函數,因此代碼量更大,但除此之外,您可以使用組合的過濾/映射函數編寫更多簡潔的代碼。
  • 最好的賣點之一是,您不僅可以使用map_filter()從序列中刪除元素,還可以使用它來注入其他元素。
  • 我當然願意提供任何建議或改進。
+0

這通常通過像「flatmap」的名字去的,因爲它的扁平化和地圖組成。通過itertools,你通常會做'chain.from_iterable(map(whatever,whatever))'。 – user2357112

+0

請原諒我的無知:來自[我讀過](https://docs.python.org/3/whatsnew/3.3.html#pep-380)'yield from'從一個生成器獲取值,而不是一個簡單的函數。否則,你可能只是''yield函數(i)' – Pynchia

+0

一個生成器只是一個函數(用'def ...'創建),它使用yield而不是'return',@Pynchia。 –

回答

2

您可以定義生成器表達式:

>>> values = range(0, 10) 
>>> evens = (value for value in values if value % 2) 
>>> even_squares = (even * even for even in evens) 
>>> list(even_squares) 
[0, 4, 16, 36, 64] 
相關問題