[英]Trying to use a loop to print each item in the list and then delete item Python
[英]Python “for in” loop to print the last item in the list
最近我學習了列表和for循環,以及指示和刪除列表中最后一項的命令.pop()
。
所以我試着編寫一個代碼來逐個刪除列表中的最后一項,直到它只剩下一個項目。
代碼是:
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
for i in list_A:
print(list_A.pop())
if 'c' not in list_A:
break
print("job done.")
python 3.6的輸出給了我:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
j
i
h
g
f
job done.
正如你所看到的,它確實有效,但只有一半呢?
我在期待:
j
i
h
g
f
e
d
c
job done
我的意思是,如果它返回一些錯誤,我會更舒服,這意味着代碼不對。 但為什么它有效,但不是完整的方式?
你在迭代它時改變列表。
您可以使用while
循環來執行此操作:
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
while 'c' in list_A:
print(list_A.pop())
print('job done')
輸出:
j i h g f e d c job done
一種更有效的方法是確定sentinel字符的第一個實例的索引,並刪除它和列表的其余部分(盡管字符在刪除時不會打印):
try:
pos = list_A.index('c')
list_A[:] = list_A[:pos]
# del list_A[pos:] # more efficient alternative suggested by @ShadowRanger
except ValueError as e:
pass
在Python中使用for..in
循環時,您不應該修改列表。
這里發生的事情如下:
a
開始 pop()
刪除最后一個列表條目,因此在第一個循環迭代中,您將刪除最后一個字母j
並打印它 e
時,從列表中刪除並打印f
a
到e
因為你只是遍歷e
循環的工作已經完成 很難說你想在這里做什么,因為它更多的是玩弄而不是完成任務。 無論何時打算在循環內編輯列表,我建議使用while
循環。 具有適當語義的示例可能如下所示:
while list_A:
print(list_A.pop())
if "c" not in list_A:
break
只要列表中有項目,此循環就會一直存在,只有在列表中沒有c
才會停止。
我最近回答了一個類似的問題,它歸結為:不要修改你迭代的序列。
使用自定義迭代器(來自我的另一個答案 )顯示發生了什么:
class CustomIterator(object):
def __init__(self, seq):
self.seq = seq
self.idx = 0
def __iter__(self):
return self
def __next__(self):
print('give next element:', self.idx)
for idx, item in enumerate(self.seq):
if idx == self.idx:
print(idx, '--->', item)
else:
print(idx, ' ', item)
try:
nxtitem = self.seq[self.idx]
except IndexError:
raise StopIteration
self.idx += 1
return nxtitem
next = __next__ # py2 compat
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
for i in CustomIterator(list_A):
print(list_A.pop())
if 'c' not in list_A:
break
哪個印刷品:
give next element: 0
0 ---> a
1 b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
9 j
j
give next element: 1
0 a
1 ---> b
2 c
3 d
4 e
5 f
6 g
7 h
8 i
i
give next element: 2
0 a
1 b
2 ---> c
3 d
4 e
5 f
6 g
7 h
h
give next element: 3
0 a
1 b
2 c
3 ---> d
4 e
5 f
6 g
g
give next element: 4
0 a
1 b
2 c
3 d
4 ---> e
5 f
f
give next element: 5
0 a
1 b
2 c
3 d
4 e
所以它並沒有因為break
而結束,而是因為它遍及整個列表(或者更好:直到沒有更多的項目!)。
此外, 'c' not in listA
是一個O(n)
操作,所以你的循環實際上是O(n**2)
。 為什么不找到'c'
的第一個索引並簡單地迭代直到你在那里:
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
try:
c_index = list_A.index('c')
except ValueError:
# no 'c' in the list, probably should do something more useful here ...
pass
else:
for item in reversed(list_A[c_index:]): # print the items
print(item)
del list_A[c_index:] # remove the items from the list
打印(如預期):
j
i
h
g
f
e
d
c
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
while list_A: # while list_A has elements, in case 'c' wasn't present
el = list_A.pop() # save the last element
print(el)
if 'c'==el: # if 'c' was popped (reached)
break
print("job done.")
這樣,即使'c'
不存在,它也會打印所有內容然后退出。 這也避免了檢查每次迭代是否存在'c'
,這需要時間。
基於@ MSeifert的注釋,如果循環不應該停在第一個c
彈出而是在列表沒有c
時停止,對上面代碼的一點修改會導致:
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'c', 'h', 'i', 'j']
while list_A:
print(list_A.pop())
if 'c' not in list_A:
break
print("job done.")
我們可以走得更快,但我不知道你是否學會了列表切片和補償,所以這里有一個更好更快的解決方案:
list_A = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
try:
p=list_A.index('c')
r='\n'.join(list_A[list_A.index('c'):][::-1])
except ValueError:
r='\n'.join(list_A[::-1])
print(r)
print('job done.')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.