pythonic方法迭代列表的一部分

Cla*_*diu 52 python iteration list

我想迭代列表中的所有内容,除了前几个元素,例如:

for line in lines[2:]:
    foo(line)
Run Code Online (Sandbox Code Playgroud)

这是简洁的,但复制整个列表,这是不必要的.我可以:

del lines[0:2]
for line in lines:
    foo(line)
Run Code Online (Sandbox Code Playgroud)

但这会修改​​列表,这并不总是好的.

我可以做这个:

for i in xrange(2, len(lines)):
    line = lines[i]
    foo(line)
Run Code Online (Sandbox Code Playgroud)

但是,这只是粗略的.

更好的可能是这个:

for i,line in enumerate(lines):
    if i < 2: continue
    foo(line)
Run Code Online (Sandbox Code Playgroud)

但它并不像第一个例子那么明显.

那么:这样做的方法与第一个例子一样明显,但不会不必要地复制列表?

sou*_*eck 43

你可以尝试itertools.islice(iterable[, start], stop[, step]):

import itertools
for line in itertools.islice(list , start, stop):
     foo(line)
Run Code Online (Sandbox Code Playgroud)

  • 警告:与`list1 [start:stop]`相比,*效率极低.例如,`islice(list1,100000,11001)`将*首先*迭代前99,999个值(只是不会返回它们).使用cProfile自己尝试一下; 它也在文档中. (8认同)
  • @NullUserException 欢呼!本来想补充一下,但我的电脑出了点问题 (3认同)
  • 很棒的是: `for line in lazy(list)[:2]: foo(line)`,其中 `lazy` 包装了可迭代对象,如果对它进行切片,则调用 `islice` ,等等。这样它看起来就像一个切片(正如它应该的那样)。 (2认同)

Eth*_*man 10

在大多数情况下,原始解决方案是合适的解决方案.

for line in lines[2:]:
    foo(line)
Run Code Online (Sandbox Code Playgroud)

虽然这会复制列表,但它只是一个浅层副本,并且非常快.在分析代码并发现这是一个瓶颈之前,不要担心优化.

  • ...但是如果你知道你要处理有数千或数百万元素的列表,不要嘲笑像`itertools.islice`这样的礼物.在这种情况下,值得一试. (3认同)
  • @ChrisMorgan:“在大多数情况下”这个短语并不嘲笑。 (2认同)
  • 即使它没有针对大列表进行优化,这段代码也具有小列表可读性的优点。 (2认同)

ekh*_*oro 8

虽然itertools.islice看起来是这个问题的最佳解决方案,但不知何故,额外的导入对于这么简单的事情来说似乎有些过分.

就个人而言,我发现enumerate解决方案完全可读和简洁 - 虽然我更喜欢这样写:

for index, line in enumerate(lines):
    if index >= 2:
        foo(line)
Run Code Online (Sandbox Code Playgroud)

  • 啊个人我更喜欢尽可能少的缩进.首先是错误检查+继续/返回/中断/等等,然后剩下的就是落空 (2认同)

How*_*ard 5

您可以构建一个辅助生成器:

def rangeit(lst, rng):
  for i in rng:
    yield lst[i]

for e in rangeit(["A","B","C","D","E","F"], range(2,4)):
  print(e)
Run Code Online (Sandbox Code Playgroud)