【问题标题】:Skip first entry in for loop in python?跳过python中for循环的第一个条目?
【发布时间】:2023-01-05 23:19:19
【问题描述】:

在 python 中,我该怎么做:

for car in cars:
   # Skip first and last, do work for rest

【问题讨论】:

  • 我是新手,但我一直在使用for n, i in enumerate(cars): if n!= 0: do something to i。逻辑是它为每个值添加一个“计数器”,然后您可以将其作为目标,例如if n == some_value。在这个例子中,它会对 i 的每个实例做一些事情,除了第一个。

标签: python


【解决方案1】:

要跳过 Python 中的第一个元素,您可以简单地编写

for car in cars[1:]:
    # Do What Ever you want

或跳过最后一个元素

for car in cars[:-1]:
    # Do What Ever you want

您可以将此概念用于任何 sequence(但不适用于任何 iterable)。

【讨论】:

  • 不是针对所有iterables,而是针对所有sequences
  • 内存使用情况如何?切片是否制作子序列的新副本?
  • @Voyager 是的,它确实制作了新副本。
【解决方案2】:

其他答案仅适用于序列。

对于任何可迭代对象,跳过第一项:

itercars = iter(cars)
next(itercars)
for car in itercars:
    # do work

如果你想跳过最后一个,你可以这样做:

itercars = iter(cars)
# add 'next(itercars)' here if you also want to skip the first
prev = next(itercars)
for car in itercars:
    # do work on 'prev' not 'car'
    # at end of loop:
    prev = car
# now you can do whatever you want to do to the last one on 'prev'

【讨论】:

  • 我发现做 cars.pop(0) 和 cars.pop() 效果很好。
  • @dreamwork801 我的回答和我在第一条评论中链接的 Sven 的答案适用于任何可迭代的,甚至是无限的,因为它们不需要在迭代开始之前对数据进行 O(n) 操作。您的建议和 Abhjit 的建议都只适用于序列,不适用于任何可迭代的。
【解决方案3】:

跳过第一项的最佳方法是:

from itertools import islice
for car in islice(cars, 1, None):
    pass
    # do something

在这种情况下,islice1 的起点和None 的终点被调用,表示iterable 的终点。

为了能够从 iterable 的末尾跳过项目,您需要知道它的长度(对于列表总是可能的,但不一定对于您可以迭代的所有内容)。例如,islice(cars, 1, len(cars)-1) 将跳过cars 中的第一项和最后一项。

【讨论】:

  • 看看 Sven(未被充分认识的)的回答。他很好地涵盖了使用islice 在任何可迭代对象的开头和/或结尾跳过任意数量的项目,而不知道长度或一次在内存中存储比绝对必要更多的项目。
  • Sven 的回答实际上会将整个迭代器存储在内存中——collections.deque 将通过迭代器运行。尝试做一些类似 collections.deque(xrange(10000000)) 的事情。如果您想跳过第一项,则无需将所有整数存储在内存中...
  • islice 是传递给deque 的内容,而不是整个迭代器,它只是最后要跳过的项目数的长度。它不会将整个迭代器存储在内存中。
【解决方案4】:

下面是一个更通用的生成器函数,它从可迭代对象的开头和结尾跳过任意数量的项目:

def skip(iterable, at_start=0, at_end=0):
    it = iter(iterable)
    for x in itertools.islice(it, at_start):
        pass
    queue = collections.deque(itertools.islice(it, at_end))
    for x in it:
        queue.append(x)
        yield queue.popleft()

用法示例:

>>> list(skip(range(10), at_start=2, at_end=2))
[2, 3, 4, 5, 6, 7]

【讨论】:

  • 可能要为 at_end == 0 添加快速路径。
  • collections.deque(...) 将立即通过迭代器。这意味着 skip(xrange(10000000), 1) 将占用大量内存,即使它确实不应该占用。
  • @RoeeShenberg:skip(xrange(10000000), 1) 将使用at_end=0,因此deque() 的参数将是islice(it, 0),它只会消耗it 的零元素。这不会占用很多内存。
【解决方案5】:

此代码跳过列表的第一个和最后一个元素:

for item in list_name[1:-1]:
    #...do whatever

【讨论】:

  • 不要使用 list 作为变量名
  • OP 只想跳过第一个元素。为什么:-1?
  • 其实不是预订的; list这个名字可以重新绑定。这就是为什么你不应该, 而不是不能, 用它。
  • @luke14free,问题说跳过第一个元素,但他的代码注释暗示他真的想跳过第一个和最后一个。
  • @luke14free 这就是标题所说的,而不是他在代码中输入的内容:“如果是第一个或最后一个则跳过”
【解决方案6】:

这是我的首选。它不需要在循环中添加太多东西,只使用内置工具。

从...来:

for item in my_items:
  do_something(item)

到:

for i, item in enumerate(my_items):
  if i == 0:
    continue
  do_something(item)

【讨论】:

    【解决方案7】:

    例子:

    mylist=['one','two','three','four','five']
    for i in mylist[1:]:
       print(i)
    

    在 python 索引从 0 开始,我们可以使用切片运算符在迭代中进行操作。

    for i in range(1,-1):
    

    【讨论】:

      【解决方案8】:

      好吧,您的语法一开始并不是真正的 Python。

      Python 中的迭代基于容器的内容(好吧,从技术上讲,它基于迭代器),语法为 for item in container。在这种情况下,容器是 cars 列表,但你想跳过第一个和最后一个元素,所以这意味着 cars[1:-1](python 列表是从零开始的,负数从末尾开始计数,而 : 是切片语法。

      所以你要

      for c in cars[1:-1]:
          do something with c
      

      【讨论】:

      • 这不适用于可迭代对象(例如生成器),只能用于序列。
      【解决方案9】:

      基于@SvenMarnach 的回答,但更简单一些并且不使用双端队列

      >>> def skip(iterable, at_start=0, at_end=0):
          it = iter(iterable)
          it = itertools.islice(it, at_start, None)
          it, it1 = itertools.tee(it)
          it1 = itertools.islice(it1, at_end, None)
          return (next(it) for _ in it1)
      
      >>> list(skip(range(10), at_start=2, at_end=2))
      [2, 3, 4, 5, 6, 7]
      >>> list(skip(range(10), at_start=2, at_end=5))
      [2, 3, 4]
      

      另请注意,根据我的timeit 结果,这比 deque 解决方案略快

      >>> iterable=xrange(1000)
      >>> stmt1="""
      def skip(iterable, at_start=0, at_end=0):
          it = iter(iterable)
          it = itertools.islice(it, at_start, None)
          it, it1 = itertools.tee(it)
          it1 = itertools.islice(it1, at_end, None)
          return (next(it) for _ in it1)
      list(skip(iterable,2,2))
          """
      >>> stmt2="""
      def skip(iterable, at_start=0, at_end=0):
          it = iter(iterable)
          for x in itertools.islice(it, at_start):
              pass
          queue = collections.deque(itertools.islice(it, at_end))
          for x in it:
              queue.append(x)
              yield queue.popleft()
      list(skip(iterable,2,2))
              """
      >>> timeit.timeit(stmt = stmt1, setup='from __main__ import iterable, skip, itertools', number = 10000)
      2.0313770640908047
      >>> timeit.timeit(stmt = stmt2, setup='from __main__ import iterable, skip, itertools, collections', number = 10000)
      2.9903135454296716
      

      【讨论】:

      • 通过使用tee(),您仍然在内存中为生成器创建一个完整的列表,对吧? (你的it1
      【解决方案10】:

      另一种方法:

      for idx, car in enumerate(cars):
          # Skip first line.
          if not idx:
              continue
          # Skip last line.
          if idx + 1 == len(cars):
              continue
          # Real code here.
          print car
      

      【讨论】:

        【解决方案11】:

        more_itertools 项目扩展了itertools.islice 以处理负索引。

        例子

        import more_itertools as mit
        
        iterable = 'ABCDEFGH'
        list(mit.islice_extended(iterable, 1, -1))
        # Out: ['B', 'C', 'D', 'E', 'F', 'G']
        

        因此,您可以优雅地在可迭代对象的第一项和最后一项之间应用 slice 元素:

        for car in mit.islice_extended(cars, 1, -1):
            # do something
        

        【讨论】:

          【解决方案12】:

          类似于@maninthecomputer 的回答,当您需要跳过基于 int 的循环的第一次迭代时(在我的例子中是self._model.columnCount()):

          for col in range(self._model.columnCount()):
              if col == 0:
                  continue
          

          更简单地说:

          test_int = 3
          
          for col in range(test_int):
              if col == 0:
                  continue
              print(col)
          

          提供输出:

          1
          2
          3
          

          【讨论】:

            【解决方案13】:

            支持itertools.chain 的好的解决方案是使用itertools.islice 来获取可迭代的一部分:

            your_input_list = ['list', 'of', 'things']
            for i, variant in list(itertools.islice(enumerate(some_function_that_will_output_itertools_chain(your_input_list)), 1, None)):
               """
               # No need for unnecessary conditions like this:
               if i == 0:
                  continue
               """
               variant = list(variant) # (optional) converting back to list
               print(variant)
            

            【讨论】:

            • 这似乎没有添加现有答案中没有的任何信息。
            【解决方案14】:

            我是这样做的,尽管它看起来像 hack,但它每次都有效:

            ls_of_things = ['apple', 'car', 'truck', 'bike', 'banana']
            first = 0
            last = len(ls_of_things)
            for items in ls_of_things:
                if first == 0
                    first = first + 1
                    pass
                elif first == last - 1:
                    break
                else:
                    do_stuff
                    first = first + 1
                    pass
            

            【讨论】:

              猜你喜欢
              • 2012-04-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-01-08
              相关资源
              最近更新 更多