【问题标题】:Using generator items selectively有选择地使用生成器项目
【发布时间】:2018-09-04 20:13:46
【问题描述】:

假设我有一些包含大量值的数组/列表,这意味着将其中的几个加载到内存中最终会由于内存不足而导致内存错误。避免这种情况的一种方法是将这些数组/列表加载到生成器中,然后在需要时使用它们。但是,使用生成器时,您没有数组/列表那么多的控制权——这就是我的问题。

让我解释一下。

作为一个例子,我有以下代码,它会生成一个带有一些小列表的生成器。所以,是的,这根本不是内存密集型的,只是一个例子:

import numpy as np

np.random.seed(10)

number_of_lists = range(0, 5)

generator_list = (np.random.randint(0, 10, 10) for i in number_of_lists)

如果我遍历这个列表,我会得到以下信息:

for i in generator_list:
    print(i)

>> [9 4 0 1 9 0 1 8 9 0]
>> [8 6 4 3 0 4 6 8 1 8]
>> [4 1 3 6 5 3 9 6 9 1]
>> [9 4 2 6 7 8 8 9 2 0]
>> [6 7 8 1 7 1 4 0 8 5]

我想做的是对所有列表 (axis = 0) 进行元素求和。所以上面应该反过来导致:

[36, 22, 17, 17, 28, 16, 28, 31, 29, 14]

为此,我可以使用以下内容:

sum = [0]*10
for i in generator_list:
    sum += i

其中10 是列表之一的长度。

到目前为止一切顺利。我不确定是否有更好/更优化的方法,但它确实有效。

我的问题是我想确定要使用generator_list 中的哪些列表。例如,如果我想将第一个 [0] 列表中的两个、第三个列表中的一个和最后一个列表中的两个相加,即:

[9 4 0 1 9 0 1 8 9 0]
[9 4 0 1 9 0 1 8 9 0]
[4 1 3 6 5 3 9 6 9 1]
[6 7 8 1 7 1 4 0 8 5]
[6 7 8 1 7 1 4 0 8 5]

>> [34, 23, 19, 10, 35, 5, 19, 22, 43, 11]

我该怎么做呢?

在出现任何问题之前,我为什么要这样做,原因是在我的实际情况中,将数组放入生成器需要一些时间。然后,原则上我可以生成一个新的生成器,按照新列表中看到的列表顺序放入其中,但同样,这意味着我必须等待将它们放入新的生成器中。如果这种情况发生数千次(如引导程序所示),那么这将需要一些时间。使用第一个生成器,我有所有可用的列表。现在我只是希望有选择地使用它们,这样我就不必每次想要混合它时都创建一个新的生成器,并对一组新的数组/列表求和。

【问题讨论】:

  • 这是您要找的吗? stackoverflow.com/questions/5509302/…
  • 您能否澄清一下“如果我想将第一个 [0] 列表中的两个、第三个列表中的一个和最后一个列表中的 2 个相加怎么办,即:”,我不明白您是如何计算结果。
  • @rocksportrocker 所以,如果它是一个列表,而不是一个生成器,我可能会这样做:list1 = [0, 0, 2, 4, 4]sum2 = [0]*10for x in list1:sum2 += generator_list[x] 其中list1 将是一个列表需要汇总的列表。在 cmets 中写的代码并不多,抱歉...
  • @Simon 我不这么认为。正如上面的评论所示,我实际上希望创建一个列表,其中包含生成器(或列表)中列表的索引,然后求和。

标签: python generator


【解决方案1】:
import numpy as np
np.random.seed(10)

number_of_lists = range(5)

generator_list = (np.random.randint(0, 10, 10) for i in number_of_lists)

indices = [0, 0, 2, 4, 4]
assert sorted(indices) == indices, "only works for sorted list"

# sum_ = [0] * 10

# I prefer this:
sum_ = np.zeros((10,), dtype=int)

generator_index = -1

for index in indices:
    while generator_index < index:
        vector = next(generator_list)
        generator_index += 1
    sum_ += vector

print(sum_)

输出

[34 23 19 10 37  5 19 22 43 11]

【讨论】:

  • 嗯,如果我在自己的列表中执行此操作,我会收到错误:TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'。这是可以修复的,还是...?
  • 或者如果你只是把generator_list改成(np.random.rand(3, 3).ravel(order="C") for i in number_of_lists)也会出现同样的错误。
  • 基于 sum_ 的初始化,只有在添加长度为 10 的整数向量时更新才有效。使用 np.random.rand(3, 3).ravel() 时添加长度为 9 的 floats。所以调整sum_的大小和dtype,代码就可以工作了。
  • 是的,我确实想通了。谢谢。
猜你喜欢
  • 2019-08-27
  • 1970-01-01
  • 2015-09-04
  • 2016-01-23
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
相关资源
最近更新 更多