簡體   English   中英

Python“for in”循環打印列表中的最后一項

[英]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並打印它
  • 接下來的5個字母都會繼續。 您從左側迭代它們,但同時刪除右側的最后一個
  • 遇到e時,從列表中刪除並打印f
  • 此后,列表中包含的字母ae因為你只是遍歷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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM