Python 字符串数组的numpy.memmap?
是否可以使用将大型基于磁盘的字符串数组映射到内存中 我知道它可以用于浮点数等,但这个问题是专门针对字符串的 我对定长字符串和变长字符串的解决方案都感兴趣Python 字符串数组的numpy.memmap?,python,string,numpy,memory-mapped-files,large-data,Python,String,Numpy,Memory Mapped Files,Large Data,是否可以使用将大型基于磁盘的字符串数组映射到内存中 我知道它可以用于浮点数等,但这个问题是专门针对字符串的 我对定长字符串和变长字符串的解决方案都感兴趣 解决方案可以自由指定任何合理的文件格式。如果所有字符串都具有相同的长度,如术语“数组”所示,则很容易做到: a = numpy.memmap("data", dtype="S10") 长度为10的字符串就是一个例子 编辑:由于字符串显然不具有相同的长度,因此需要为文件编制索引以允许O(1)项访问。这需要读取整个文件一次,并将所有字符串的开始索
解决方案可以自由指定任何合理的文件格式。如果所有字符串都具有相同的长度,如术语“数组”所示,则很容易做到:
a = numpy.memmap("data", dtype="S10")
长度为10的字符串就是一个例子
编辑:由于字符串显然不具有相同的长度,因此需要为文件编制索引以允许O(1)项访问。这需要读取整个文件一次,并将所有字符串的开始索引存储在内存中。不幸的是,我认为没有一种纯粹的简单方法可以在不首先创建与内存中的文件大小相同的数组的情况下进行索引。不过,提取索引后可以删除此数组。最灵活的选择是切换到数据库或其他更复杂的磁盘文件结构 然而,可能有一些很好的理由让你宁愿把东西保存为纯文本文件 因为您可以控制文件的创建方式,所以一个选项是简单地写出第二个文件,该文件只包含另一个文件中每个字符串的起始位置(以字节为单位) 这需要做更多的工作,但基本上可以这样做:
class IndexedText(object):
def __init__(self, filename, mode='r'):
if mode not in ['r', 'w', 'a']:
raise ValueError('Only read, write, and append is supported')
self._mainfile = open(filename, mode)
self._idxfile = open(filename+'idx', mode)
if mode != 'w':
self.indicies = [int(line.strip()) for line in self._idxfile]
else:
self.indicies = []
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self._mainfile.close()
self._idxfile.close()
def __getitem__(self, idx):
position = self.indicies[idx]
self._mainfile.seek(position)
# You might want to remove the automatic stripping...
return self._mainfile.readline().rstrip('\n')
def write(self, line):
if not line.endswith('\n'):
line += '\n'
position = self._mainfile.tell()
self.indicies.append(position)
self._idxfile.write(str(position)+'\n')
self._mainfile.write(line)
def writelines(self, lines):
for line in lines:
self.write(line)
def main():
with IndexedText('test.txt', 'w') as outfile:
outfile.write('Yep')
outfile.write('This is a somewhat longer string!')
outfile.write('But we should be able to index this file easily')
outfile.write('Without needing to read the entire thing in first')
with IndexedText('test.txt', 'r') as infile:
print infile[2]
print infile[0]
print infile[3]
if __name__ == '__main__':
main()
@aix:至少现在的情况完全不同了。O(1)只有在为整个文件编制索引后,才能访问单个元素。字符串平均有多长?它们是由新行字符、空字符还是完全不同的字符分隔的?我控制生成文件的过程。它可以以任何格式写入数据,从而使读取过程更加轻松。@aix:字符串的长度是多少?长度的分布是什么?用固定的宽度保存它们会不会非常浪费?快进到2018年——有没有比固定字符串长度更好的方法?(例如,numpy能否将起始索引memmap解释为指向字节平面数组的指针,并将其视为字符串数组?)@user48956通常,答案可能是使用实际的数据库。