如何为一长串整数创建优化的迭代器?

Posted

技术标签:

【中文标题】如何为一长串整数创建优化的迭代器?【英文标题】:How to create an optimized iterator for a long list of integers? 【发布时间】:2017-09-27 05:12:56 【问题描述】:

假设我有一个非常大的整数列表,占用大量内存。如果列表的整数是偶数增量,那么我可以轻松地将列表表示为不占用内存的迭代器。但是对于更复杂的模式,将这个列表表示为迭代器会变得更加困难。

是否有可以分析整数列表并返回“优化”迭代器的 Python 包?或者我可以研究实现这一目标的方法?

【问题讨论】:

你描述的是compression的一种形式。 制作一个内存压缩文件怎么样? 这是一个复杂的问题。对于特定的整数模式是否存在“有用的”(即简短的)封闭形式解决方案是一个难以准确回答的数论问题。根据您的特定列表,这可能是微不足道的 - 或不可能的。研究如上所述的通用压缩可能会有所帮助。你想达到什么目的?你只是好奇吗? (没有错!) 我主要是好奇。然而,为了给出上下文,我正在想办法减少大型稀疏矩阵的数据存储需求,特别是对于稀疏矩阵向量产品。在这里,整数列表将是指向减少的非零元素列表以及元素位置的索引。 LZW 压缩看起来非常整洁。我会仔细阅读的。 你可以用谷歌搜索你的序列并希望在https://oeis.org/找到它。如果你找到了,你可以把你的整个序列压缩成一个小 ID :) 【参考方案1】:

我的概念证明,使用 lzma 库 (backport for python 2) 并压缩到内存。您可以使用磁盘上的文件代替内存缓冲区:

import io
import random
import struct
import sys

from backports import lzma

# Create array of integers with some duplicates
data = []
for i in xrange(0, 2000):
    data += [random.randint(-sys.maxint, sys.maxint)] * random.randint(0, 500)

print('Uncompressed: '.format(len(data)))
buff = io.BytesIO()

fmt = 'i'  # check https://docs.python.org/3/library/struct.html#format-characters
lzma_writer = lzma.LZMAFile(buff, 'wb')
for i in data:
    lzma_writer.write(struct.pack(fmt, i))
lzma_writer.close()
print('Compressed: '.format(len(buff.getvalue())))

buff.seek(0)
lzma_reader = lzma.LZMAFile(buff, 'rb')

size_of = struct.calcsize(fmt)


def generate():
    r = lzma_reader.read(size_of)
    while len(r) != 0:
        yield struct.unpack(fmt, r)[0]
        r = lzma_reader.read(size_of)


# Test if it is same array
res = list(generate())
print res == data

结果:

Uncompressed: 496225
Compressed: 11568
True

【讨论】:

我不久前发现并使用的另一种压缩形式是 SIMDComp 库。【参考方案2】:

我同意 Efron Licht 的观点,很明显:这完全取决于特定列表的复杂性来压缩(不是说“压缩”)。除非您的列表足够简单,可以表达为生成器,否则您唯一的选择是使用 Bartek Jablonski 答案。

【讨论】:

【参考方案3】:

您正在寻找生成器。您可以将所有自定义逻辑封装在里面。这个问题有点含糊,所以可能有助于了解这是否对您有帮助

def moreDataExists(index):
    # Your stop condition
    return True

def getNextIndex(index):
    # Your complicated pattern of going from one index to the next.
    return index

def generator(yourData):
    index = None
    while moreDataExists(index):
        index = getNextIndex(index)
        yield yourData[index]


for d in generator(data):
    doSomethingWith(d)

【讨论】:

【参考方案4】:

这很简单 - 只需用生成器包装过滤后的迭代器,例如:

for i in (_ for _ in range(int(1e7)) if str(_)==str(_)[::-1]):
    if str(i**2)==str(i**2)[::-1]:
        print(i)

【讨论】:

以上是关于如何为一长串整数创建优化的迭代器?的主要内容,如果未能解决你的问题,请参考以下文章

如何为特征矩阵创建STL输出迭代器?

如何为迭代器返回“null”值?

如何为自定义输入迭代器定义指针

代码详解生成器迭代器

python之迭代器

我将如何在 Java 中迭代堆栈 [关闭]