Python“for in”循环打印列表中的最后一项

时间:2017-09-07 01:16:47

标签: python python-3.x list for-loop

最近我了解了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

我的意思是,如果它返回一些错误,我会更舒服,这意味着代码不对。但为什么它有效,但不是完整的方式?

4 个答案:

答案 0 :(得分:5)

你在迭代它时改变列表。

您可以使用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

答案 1 :(得分:3)

在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后才会停止。

答案 2 :(得分:2)

我最近回答了一个类似的问题,归结为:不要修改你重复的序列。

使用自定义迭代器(来自another answer of mine)显示发生了什么:

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 listAO(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

答案 3 :(得分:1)

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.')