【问题标题】:Get multiple individual values from generator in Python从 Python 中的生成器获取多个单独的值
【发布时间】:2012-11-13 05:18:07
【问题描述】:

如何从迭代器的不同索引位置获取多个任意值?

How to get the n next values of a generator in a list (python)Get the nth item of a generator in Python 描述了使用itertools.islice 从迭代器中获取任意元素或连续子集。但是,如果我想要迭代器中不同位置的多个任意元素,而你不能只使用 islice 的 step 参数呢?

我正在尝试解决 Project Euler 的problem 40。我用

生成了一串连接整数
iteration = (i for i in ''.join(map(str, (i for i in xrange(1,10**6)))))

现在我想获取索引为 1、10、100、1000、10000、100000、1000000 的元素,从 1 开始计数。我不能在这里使用 islice,因为每次调用 next 都会将当前值转换为向右让步。例如

next(islice(iteration, 1, 2)) + next(islice(iteration, 3, 4))

产生“26”而不是“24”。

更新(25.11.12,4:43 UTC+0)

感谢所有建议。我当前的代码如下所示:

it = (i for i in ''.join(map(str, (i for i in xrange(1,10**6)))))
ds = [int(nth(it, 10**i-10**(i-1)-1)) for i in range(7)]
return product(ds)

nth 的丑陋论点是生成一个由 0、8、89、899、8999 等组成的序列。

【问题讨论】:

  • 当前代码的一个问题是它不会延迟生成数字(例如,将 10**6 更改为 10**7)——''.join 将消耗它传递的内容。跨度>

标签: python iterator generator itertools


【解决方案1】:

这是来自the "recipes" section of the itertools documentation。它返回iterablenth 元素,并在执行过程中使用它:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

您可以通过顺序调用它来获取第 1、10、100 个等元素(注意迭代器被消耗,并且是零索引的):

first = nth(iteration, 0)
tenth = nth(iteration, 8)  # since we've already taken one
hundredth = nth(iteration, 89)  # since we've already taken ten
# etc

或者,您可以使用 tee 并每次使用带有不同迭代器的 nth。这样你就不必担心你的单个迭代器被消耗掉了。另一方面,如果您的迭代器很长,您可能会开始吞噬内存。

【讨论】:

    【解决方案2】:

    (请注意,有更快的方法来求解 Euler #40。)

    我的工作方式会有所不同。而不是使用nth:

    >>> from itertools import chain, count, islice
    >>> 
    >>> it = chain.from_iterable(str(i) for i in count(1))
    >>> wanted = {10**i for i in range(7)}
    >>> scan_region = islice(it, max(wanted)+1)
    >>> digits = [int(x) for i, x in enumerate(scan_region, 1) if i in wanted]
    >>> digits
    [1, 1, 5, 3, 7, 2, 1]
    

    这样我就不必做任何减法来确保我有正确的索引。

    【讨论】:

      【解决方案3】:

      除了查看nth 之外,我还会考虑简化您的生成器:

      from itertools import count
      
      def concat():
          for i in count(1):
              for j in str(i):
                  yield int(j)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-25
        • 1970-01-01
        • 2011-01-26
        • 1970-01-01
        • 1970-01-01
        • 2022-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多