如何从可迭代的保持原始索引中枚举选定的元素?

How to enumerate over selected elements from an iterable keeping original indices?

我运行进入selected元素上使用枚举器的情况,形成一个可迭代(即sequenceiterator 或类似的)并希望返回 original 索引 而不是默认值 count,从 0 开始,一直到 len(iterable) - 1

一个非常幼稚的方法是声明一个新的生成器对象,称为_enumerate()

>>> def _enumerate(iterable, offset = 0, step = 1):
    index = offset
    for element in iterable:
        yield index, element
        index += step

...一个新的列表对象months.

>>> months = ["January", "February", "March", "April", "May", "June",
              "July", "August", "September", "October", "November", "December"]

使用 Python 内置 enumerate 函数 将为 [5::2] 切片生成此 输出

>>> for index, element in enumerate(months[5::2]):
    print(index, element)


    0 June
    1 August
    2 October
    3 December

我们自己的枚举器_enumerate预期输出再次用于[5::2]切片:

>>> for index, element in _enumerate(months[5::2], offset = 5, step = 2):
    print(index, element)


    5 June
    7 August
    9 October
    11 December

你知道更好、更 pythonic 和更易读的解决方案吗? :)

我不喜欢用range(len(...,但也许在这里没问题。

>>> months = ["January", "February", "March", "April", "May", "June",
...           "July", "August", "September", "October", "November", "December"]
>>> print(*('{:>2} {}'.format(i, months[i]) for i in range(len(months))[5::2]), sep='\n')
 5 June
 7 August
 9 October
11 December

单行展开:

offset = 5
step = 2
r = range(len(months))

for i in r[offset::step]:
    print('{:>2} {}'.format(i, months[i]))
import itertools as it

months = [
    "January", "February", "March", "April", "May", "June", "July",
    "August", "September", "October", "November", "December"
]

print list(
    it.islice(it.izip(it.count(1), months), 5, len(months), 2)
)

回答评论中的进一步问题:

  • 普通切片不适用于 itertools.izip,因为它不支持 __getitem__ 方法。

  • 是的,itertools.izip 已从 Python 3 中删除,常规内置 zip 使用相同的生成器语义。

这里是我的评论作为回答;)

months = ["January", "February", "March", "April", "May", "June",
          "July", "August", "September", "October", "November", "December"]

offset = 5
step = 2
for index, element in enumerate(months[offset::step]):

    # recalculate original index
    index = offset + index*step

    # actually repetition of the month is trivial,
    # but I put it just to show that the index is right
    print(index, element, months[index])

打印:

5 June June
7 August August
9 October October
11 December December

您可以使用 itertools.islice() + enumerate() 到 select 个具有原始索引的元素:

>>> import calendar
>>> from itertools import islice
>>> for i, month in islice(enumerate(calendar.month_abbr), 6, None, 2):
...     print(i, month)
... 
6 Jun
8 Aug
10 Oct
12 Dec

它不复制切片信息并使用具有熟悉行为的现有函数。

或者如果你知道原来的iterable很小;你可以打电话给 list():

>>> list(enumerate(calendar.month_abbr))[6::2]
[(6, 'Jun'), (8, 'Aug'), (10, 'Oct'), (12, 'Dec')]