2014-03-26 48 views
3

我想要一個函數,它接受一個列表並返回該列表,其中任何小於0或大於「upper」的元素都將被刪除。確保python列表的值範圍

我想出如何與列表理解這樣做,但我不明白,爲什麼這並不工作:

dim = 4 

def ensure_values(l, upper=dim**2): 
    for i in l: 
     if i < 0 or i >= upper: 
      l.remove(i) 
    return l 

l = [0,2,-3,5] 

ensure_values(l) 
[0,2,-3,5] 

我預期[0,2,5]。

+3

當您修改它時列表正在改變,導致迭代跳過值。在這種情況下,列表理解更好,但如果需要,可以創建要刪除的值列表,然後再刪除這些值。 – swstephe

+0

它確實有效。開始一個新的會話,複製粘貼你的代碼,它的工作原理。另外@swstephe說:例如使用一個副本'l2 = l [:]',並從l2中刪除,並返回l2。 – fredtantini

+0

只要列表中只有一個超出範圍的值,它就會生效。 – kojiro

回答

1

你可以改變你的循環,以便迭代列表的副本,避免修改你正在迭代的列表,因爲這在許多情況下不起作用。

dim = 4 

def ensure_values(l, upper=dim**2): 
    for i in l[:]: # iterate over copy of list 
     if i < 0 or i >= upper: 
      l.remove(i) 
    return l 

l = [0, 2, -3, 20, 5] 

print ensure_values(l) # -> [0, 2, 5] 

更「Python化」的方式來做到這一點—因爲它的短,不需要名單—的副本將使用列表理解。注意條件必須被逆轉,因爲它現在被用於確定何時保留元素。

l = [i for i in l if i >= 0 and i < dim**2] 

print l # -> [0, 2, 5] 
+0

這會起作用,但這不是最佳做法。建立一個只包含所需要素的新清單最好,而不是改變原來的清單。在Python中,由於「命令 - 查詢分離」,所以最好從任何會改變參數的函數中返回'None'。 http://stackoverflow.com/questions/9777122/why-does-sort-cause-the-list-to-be-none-in-python – steveha

+0

@steveha:雖然我同意,這不是OP所要求的。恕我直言,最好的方法是根本不使用函數,而是使用我的更新答案中顯示的list-comp。 – martineau

+0

@steveha:P.S.反對返回None而不是突變參數的一個論據是,這意味着結果不能與另一個操作鏈接 - 因此可能有其他考慮因素。 – martineau

3

Python中的最佳實踐是讓您的函數返回一個僅包含所需元素的新列表。這最好用列表理解來完成。

dim = 4 

def ensure_values(lst, upper=dim**2): 
    return [n for n in lst if 0 < n <= upper] 

lst = [0,2,-3,5] 

assert ensure_values(lst) == [2, 5] 

請注意,我能夠使用表達式0 < n <= upper。這在C語言或大多數其他語言中都不合法,但在Python中它是合法的,並且做到了人們所期望的。

此外,我建議不要使用l作爲變量名稱。它看起來幾乎完全像許多字體中的1I。建議的做法是使用lstL作爲列表的簡稱。

使用l作爲變量名在Python的PEP 8編碼風格指南中特別不推薦使用。這裏有一個鏈接:

http://legacy.python.org/dev/peps/pep-0008/#id29

0

爲什麼不使用過濾器?

def ensure_values(l, upper=dim**2): 
    return filter(lambda x: x>0 or x<upper, l)