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

时间:2015-07-29 07:35:40

标签: python python-3.x generator enumerate

我遇到使用选定的元素上的枚举器形成可迭代的(即序列迭代器< / em>或类似的)并且希望返回 原始索引而不是默认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"]

使用Pythons 内置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和更易读的解决方案吗?:)

4 个答案:

答案 0 :(得分:2)

这里我的评论作为答案;)

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

答案 1 :(得分:1)

我不喜欢使用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]))

答案 2 :(得分:1)

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使用相同的生成器语义。

答案 3 :(得分:0)

您可以使用itertools.islice() + enumerate()来选择具有原始索引的元素:

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

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

或者如果你知道原始的可迭代性很小;你可以致电list()

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