优雅的方式来跳过迭代中的元素 [英] Elegant way to skip elements in an iterable

查看:141
本文介绍了优雅的方式来跳过迭代中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很大的可迭代,实际上是一个很大的迭代次数:

I've got a large iterable, in fact, a large iterable given by:

itertools.permutations(range(10))

我想访问第一百万个元素。我已经通过一些不同的方式解决了问题。

I would like to access to the millionth element. I alredy have problem solved in some different ways.


  1. 将可迭代转换为列表并获得1000000个元素:

  1. Casting iterable to list and getting 1000000th element:

return list(permutations(range(10)))[999999]


  • 手动滑动元素直到999999:

  • Manually skiping elements till 999999:

    p = permutations(range(10))
    for i in xrange(999999): p.next()
    return p.next()
    


  • 手动滑动元素v2:

  • Manually skiping elements v2:

    p = permutations(range(10))
    for i, element in enumerate(p):
        if i == 999999:
            return element
    


  • 使用来自itertools的islice:

  • Using islice from itertools:

    return islice(permutations(range(10)), 999999, 1000000).next()
    


  • 但我仍然觉得他们中没有一个是蟒蛇的优雅方式。第一个选项太昂贵了,它需要计算整个迭代只是为了访问单个元素。如果我没有错,islice在内部执行的方法与我在方法2中所做的相同,并且几乎完全是第3次,也许它有更多的冗余操作。

    But I still don't feel like none of them is the python's elegant way to do that. First option is just too expensive, it needs to compute the whole iterable just to access a single element. If I'm not wrong, islice does internally the same computation I just did in method 2, and is almost exactly as 3rd, maybe it has even more redundant operations.

    所以,我只是好奇,想知道是否有python以其他方式访问迭代的具体元素,或者至少以更优雅的方式跳过第一个元素,或者如果我只需要使用一个以上。

    So, I'm just curious, wondering if there is in python some other way to access to a concrete element of an iterable, or at least to skip the first elements, in some more elegant way, or if I just need to use one of the aboves.

    推荐答案

    使用 itertools 食谱消费 跳过 n 元素:

    def consume(iterator, n):
        "Advance the iterator n-steps ahead. If n is none, consume entirely."
        # Use functions that consume iterators at C speed.
        if n is None:
            # feed the entire iterator into a zero-length deque
            collections.deque(iterator, maxlen=0)
        else:
            # advance to the empty slice starting at position n
            next(islice(iterator, n, n), None)
    

    注意那里的 islice()调用;它使用 n,n ,实际上没有返回任何,以及 next()函数回退到默认值。

    Note the islice() call there; it uses n, n, effectively not returning anything, and the next() function falls back to the default.

    简化为您想要跳过999999个元素的示例,然后返回元素1000000:

    Simplified to your example, where you want to skip 999999 elements, then return element 1000000:

    return next(islice(permutations(range(10)), 999999, 1000000))
    

    islice()处理C中的迭代器,这是Python循环无法击败的东西。

    islice() processes the iterator in C, something that Python loops cannot beat.

    为了说明,以下是每种方法仅重复10次的时间:

    To illustrate, here are the timings for just 10 repeats of each method:

    >>> from itertools import islice, permutations
    >>> from timeit import timeit
    >>> def list_index():
    ...     return list(permutations(range(10)))[999999]
    ... 
    >>> def for_loop():
    ...     p = permutations(range(10))
    ...     for i in xrange(999999): p.next()
    ...     return p.next()
    ... 
    >>> def enumerate_loop():
    ...     p = permutations(range(10))
    ...     for i, element in enumerate(p):
    ...         if i == 999999:
    ...             return element
    ... 
    >>> def islice_next():
    ...     return next(islice(permutations(range(10)), 999999, 1000000))
    ... 
    >>> timeit('f()', 'from __main__ import list_index as f', number=10)
    5.550895929336548
    >>> timeit('f()', 'from __main__ import for_loop as f', number=10)
    1.6166789531707764
    >>> timeit('f()', 'from __main__ import enumerate_loop as f', number=10)
    1.2498459815979004
    >>> timeit('f()', 'from __main__ import islice_next as f', number=10)
    0.18969106674194336
    

    islice()方法比下一个最快的方法快近7倍。

    The islice() method is nearly 7 times faster than the next fastest method.

    这篇关于优雅的方式来跳过迭代中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆