2013-05-30 28 views
1

我想排除理解中返回無的案例。 以下實現它,但導致兩次調用該函數!如何從理解中排除案例

>>> def func(x): 
...  if x>10: 
...   return None 
...  else: 
...   return x*2 
...   
>>> result1=[func(x) for x in l if func(x) is not None] 
>>> result1 
[4, 8, 14, 6] 

什麼是出路?

回答

4
result1[:] = [x for x in map(func, l) if x is not None] 

關於Python 2.x的使用itertools.imap

注:filter(None, map(func, l))通常會工作,但也將消除0(因爲它被認爲是空的)

+0

謝謝 - 是否imap給地圖帶來額外優勢? – IUnknown

+0

@IUnknown它返回一個迭代器而不是一個列表。因此,對於龐大的數據集更加高效,對於小型列表來說,您將看不到太多的區別 – jamylak

+0

只是再一個問題 - 我如何調用一個需要一些附加參數的函數的映射 - def func(x,multiplier )。 – IUnknown

2

這個怎麼樣代碼:

print([x*2 for x in l if x <= 10]) 

編輯

通常它可以採取的形式:

print([process(x) for x in l if is_valid(x)] 
+0

+ +1更有意義,只要做到這一點 – jamylak

+0

真實 - 但我有的功能更復雜,並不完全依賴於輸入。 – IUnknown

+0

在這種情況下,您可以分開這些功能。一個會檢查元素是否有效處理,第二個會處理它。 – StKiller

1
def func(x): 
    if x>10: 
     return None 
    else: 
     return x*2 

lst = [2, 4, 12, 7, 30, 3] 

# original 
result0 = [func(x) for x in lst if func(x) is not None] 

# map... on Python 2.x, use itertools.imap() 
result1 = [x for x in map(func, lst) if x is not None] 
assert result1 == result0 

# generator expression 
result2 = [x for x in (func(y) for y in lst) if x is not None] 
assert result2 == result0 

# rewrite function as a generator function 
def func_gen(iterable): 
    for x in iterable: 
     if x <= 10: 
      yield x*2 

# no need to filter; filtering happens in generator function 
result3 = list(func_gen(lst)) 
assert result3 == result0 


# build a filtering generator out of parts 
def fn_x2(x): 
    return x * 2 

def filter_leq10(x): 
    return x <= 10 

def make_filtering_gen_func(fn, flt, name="anonymous"): 
    def anonymous(iterable): 
     for x in iterable: 
      if flt(x): 
       yield fn(x) 
    anonymous.__name__ = name 
    return anonymous 

func_gen1 = make_filtering_gen_func(fn_x2, filter_leq10) 
result4 = list(func_gen1(lst)) 
assert result4 == result0 

評論。

@jamylak已經向您展示瞭如何使用map()itertools.imap()來解決這個問題。但由於某種原因,他/她使用切片顯示重寫現有列表。我沒有看到有任何理由要這樣做,所以我只是用一個變量名綁定來展示它。

map()更常見的推薦替代方案是一個生成器表達式,所以我展示瞭如何在列表理解中使用一個表達式。

但是對於這樣的情況,我通常更喜歡將函數重寫爲只生成所需數字的生成器。無論如何,你將會調用這個函數,所以不要讓它返回一個不想要的值的標記值,而只是讓它產生所需的值。

最後,用零件構建濾波生成器的功能方法!你可以傳入任何帶有一個參數的函數(並且記住你可以使用functools.partial()來綁定其他參數並獲得一個只帶一個參數的函數對象),並且傳遞一個選擇值的過濾函數。它建立一個函數對象並返回它,它會自動處理「樣板」,爲您添加for循環,if測試以過濾,然後yield與結果。

相關問題