Python:动态处理大型文档的行

时间:2017-05-06 12:25:14

标签: python readlines

我的文档看起来有点像这样:

key1 value_1_1 value_1_2 value_1_3 etc
key2 value_2_1 value_2_2 value_2_3 etc
key3 value_3_1 value_3_2 value_3_3 etc
etc

每个key都是一个字符串,每个value都是一个浮点数,所有都用空格分隔。每行有数百个与之关联的值,并且有数十万行。每条线都需要以特定的方式处理,但由于我的程序只需要来自一小部分线的信息,所以立即处理每条线似乎是一个巨大的浪费时间。目前,我只有一个每个未处理行的列表,并维护一个包含每个key的单独列表。当我需要访问一行时,我将使用key列表来查找我需要的行的索引,然后处理行列表中该索引处的行。我的程序可能会多次查询相同的行,这会导致一遍又一遍地冗余地处理同一行,但似乎仍然比从一开始就处理每一行更好。

我的问题是,有没有更有效的方法来做我正在做的事情?

(如果我需要澄清,请告诉我)

谢谢!

2 个答案:

答案 0 :(得分:3)

首先,我会将您的行存储在dict中。这可能使得基于密钥的查找速度更快。制作这个词典可以像d = dict(line.split(' ', 1) for line in file_obj)一样简单。例如,如果键具有固定的宽度,只需切割线就可以加快速度。

接下来,如果行处理的计算量很大,则可以缓冲结果。我通过继承dict

来解决这个问题
class BufferedDict(dict):
    def __init__(self, file_obj):
        self.file_dict = dict(line.split(' ', 1) for line in file_obj)

    def __getitem__(self, key):
        if key not in self:
            self[key] = process_line(self.file_dict[key])
        return super(BufferedDict, self).__getitem__(key)

def process_line(line):
    """Your computationally heavy line processing function"""

这样,如果您拨打my_buffered_dict[key],只有处理后的版本尚未提供时才会处理该行。

答案 1 :(得分:1)

这是一个扫描文件的类,只是缓存文件偏移量。只有在访问其键时才会处理行。 __getitem__缓存已处理的行。

class DataFileDict:
    def __init__(self, datafile):
        self._index = {}
        self._file = datafile

        # build index of key-file offsets
        loc = self._file.tell()
        for line in self._file:
            key = line.split(None, 1)[0]
            self._index[key] = loc
            loc = self._file.tell()

    def __getitem__(self, key):
        retval = self._index[key]
        if isinstance(retval, int):
            self._file.seek(retval)
            line = self._file.readline()
            retval = self._index[key] = list(map(float, line.split()[1:]))
            print("read and return value for {} from file".format(key))
        else:
            print("returning cached value for {}".format(key))
        return retval

if __name__ == "__main__":
    from io import StringIO

    sample = StringIO("""\
A 1 2 3 4 5
B 6 7 8 9 10
C 5 6 7 8 1 2 3 4 5 6 7
""")

    reader = DataFileDict(sample))
    print(reader['A'])
    print(reader['B'])
    print(reader['A'])
    print(reader['C'])
    print(reader['D'])  # KeyError

打印

read and return value for A from file
[1.0, 2.0, 3.0, 4.0, 5.0]
read and return value for B from file
[6.0, 7.0, 8.0, 9.0, 10.0]
returning cached value for A
[1.0, 2.0, 3.0, 4.0, 5.0]
read and return value for C from file
[5.0, 6.0, 7.0, 8.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
Traceback (most recent call last):
  File "C:/Users/ptmcg/.PyCharm2017.1/config/scratches/scratch.py", line 64, in <module>
    print(reader['D'])  # KeyError
  File "C:/Users/ptmcg/.PyCharm2017.1/config/scratches/scratch.py", line 28, in __getitem__
    retval = self._index[key]
KeyError: 'D'