2011-05-05 41 views
3

是否可以使用numpy.memmap字符串的大型磁盤陣列映射到內存中?numpy.memmap爲字符串數組?

我知道這可以做浮動和類似的,但這個問題是專門關於字符串。

我對固定長度和可變長度字符串的解決方案感興趣。

該解決方案可以自由指定任何合理的文件格式。

回答

2

如果所有的字符串具有相同的長度,如由「陣列」術語建議,這是容易實現:

a = numpy.memmap("data", dtype="S10") 

將是長度的字符串一個例子10.

編輯:由於顯然這些字符串的長度不相同,因此您需要索引文件以允許O(1)項訪問。這需要讀取整個文件一次並將所有字符串的起始索引存儲在內存中。不幸的是,我不認爲有沒有一種純粹的NumPy索引方式,而不是先創建一個與內存中文件大小相同的數組。儘管這個數組在提取索引後可以被刪除。

+0

可悲的是,事實並非如此。這是一個表演塞? – NPE 2011-05-05 11:14:43

+0

@aix:至少這是一個完全不同的情況。 O(1)只能在索引整個文件之後訪問單個元素。平均多長時間?它們是由新行字符還是空字符或完全不同的東西分開的? – 2011-05-05 11:20:04

+0

我控制生成文件的過程。它可以以任何格式寫入數據,使讀取過程變得簡單。 – NPE 2011-05-05 11:32:03

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()