2011-03-29 96 views
2

請直接指出。列表例如lst = [1, 1, 1, 0, 0, 0],現在我想將1更改爲0,作爲lst = [0, 0, 0, 0, 0, 0]關於python列表元素和列表解析的一些問題

我的原始溶液下面喜歡:

for item in lst: 

    if item == 1: 

     item = 0 

實際上,結果列表仍然LST = [1,1,1,0,0,0]。

Q1:除了使用列表理解之外,還有其他解決方案可以解決嗎?

Q2:如何在正確的列表解析時寫入更多的if else for呢?所以我嘗試了以下四種款式:

No.1 lst = [0 if item == 1 for item in lst] # Returns syntax error 

No.2 lst = [0 for item in lst if item == 1] # Returns [0, 0, 0] 

No.3 lst = [0 if item == 1 else item for item in lst] # Returns [0, 0, 0, 0, 0, 0] 

No.4 lst = [0 for item in lst if item == 1 else item] # Returns syntax error 

回答

3

列表理解和for item in iterable都不會改變列表。在前一種情況下,這在設計上(實際上)是不可能的,在後一種情況下,這是因爲Python只是傳遞值。

您可以使用for循環並更改特定索引處的值。只是在迭代時不要刪除或添加任何東西。 enumerate可以讓你有你的蛋糕(物品)和吃它(也索引)。

for i, item in enumerate(lst): 
    if item == 1: 
     list[i] = 0 

一般列表理解的形式爲[expression for target in expression if condition]的。最後的可選篩選部分只能跳過一個項目(將其視爲if not condition: continue),選擇要放入正在生成的列表中的項目發生在第一個expression-幾個版本之前,添加了條件表達式(expression if condition else expression),所以你可以在表達式中做一些基本的選擇。在一個表達式中做兩次或更多的事情真的會推動它,所以避免使用更復雜的邏輯。

+1

Python不會提取循環計數器「按值」 - 請參閱我對Mike Lewis的回答的評論。此外,使用列表理解來修改列表項是很容易的:'a = [[],[]]; [x.append(0)for x in a]'。誠然,這不完全是列表理解。 – 2011-03-29 16:26:33

+0

@Sven:這是有價值的。但是在python中的其他地方,這個值是一個參考。如果它是一個可變對象的引用,那麼你當然可以修改它。但重新分配它並不會改變列表中的引用(這就是「...引用」意味着什麼)。是的,你可以隨時修改可變對象,包括列表解析。 – delnan 2011-03-29 17:45:50

0

lst = [0 for item in lst]可能是最簡單的。也許不是最快的(特別是數百萬和數十億的元素)。

您也可以嘗試lst = [ 0 if item==1 else 0 for item in lst]

3

你可以這樣做:

for x, item in enumerate(lst): 
    if item == 1: 
     lst[x] = 0 

這工作,因爲枚舉返回產生(指數,項目)

這樣,您就可以檢查的元組的迭代器該項目的價值,但也知道你目前在哪個索引,所以你可以編輯參考。

並回答3號,你想:

>>> lst = [1, 1, 1, 0, 0, 0] 
>>> [0 if x == 1 else x for x in lst] 
[0, 0, 0, 0, 0, 0] 
>>> 
+0

這是不正確的,循環計數器「按值」提取。試試'a = [[],[]];因爲我在a:i.append(0)'看到你實際上*可以*修改列表項目的方式OP試圖,但只有當列表項目是可變的。 – 2011-03-29 16:22:51

1

Q1。 for循環中迭代器的賦值不會反射回列表。您需要使用正常a[b]=c語法回來後的變化

for i, item in enumerate(lst): 
     if item == 1: 
      lst[i] = 0 

Q2。 Number 3.

x if y else z是Python中的一個特殊表達式。這與C語言中的y ? x : z相對應。您不能忽略else部分,因此Number 1是語法錯誤。

2號表示僅會發射滿足item == 1的物品。更好的說明示例:

>>> [i for i in range(10) if i % 4 == 0] 
[0, 4, 8] 
+0

對for循環中迭代器的更改可能會反映回列表 - 請參閱我對Mike Lewis的答案的評論。 – 2011-03-29 16:29:24

+0

@Sven:澄清說「轉讓」。 – kennytm 2011-03-29 16:48:20

1

正如你已經知道的,列表理解沒有。 3是正確的語法。一般一個輔助功能,能有這樣的更加清晰:

def modify(value): 
    if value == 1: 
     return 0 
    else: 
     return value 

lst = [modify(item) for item in lst] 

要以達到相同的效果for循環例如,你可以使用enumerate()

for index, item in enumerate(lst): 
    if item == 1: 
    lst[index] = 0 
0

for循環,你正在使用列表元素的副本,而不是實際的列表。在任何情況下迭代遍歷它時修改序列並不安全。

你可以這樣做:

while 1 in lst: 
    lst[lst.index(1)] = 0 

達到你想要的東西沒有一個列表理解。

0

您的for循環不起作用的原因是更改item的值僅更改了item的值。 item最初指向列表中的相同元素,但重新分配它只會改變它指向的內容;它不會修改列表元素。

要真正修改列表,您需要知道您正在查看的列表中的哪個項目。您可以通過使用enumerate()來完成此操作,它可讓您在循環體內訪問項目值及其索引(列表中的位置)。

for index, item in enumerate(lst): 
    if item == 1: 
     lst[index] = 0 

這樣做,這樣(而不是一個列表理解,正如其他人所建議的)確實沒有上榜,如果列表很大可能是有用的另一個副本的優勢。

0

如果您想更新就地列表(即,而無需創建一個新的列表),然後將下面的代碼將工作:

for index, item in enumerate(lst): 
    if item == 1: 
     lst[i] = 0 

在你原來的代碼,每次輪循環中的變量item被分配列表中的下一個值,然後如果該值爲1,則將0分配給item,但是不是更改列表 - 它只是更改變量item

要創建一個新列表,您的解決方案(3)很好。