2016-03-03 55 views
2

我需要将一个潜在的大型csv文件上传到我的应用程序中。该文件的每个部分用#TYPE *表示。我应该如何将它分成块并对每个块进行进一步处理?每个块都是一个标题列表,后面跟着所有的值。如何通过Python中的字符串分隔符将文件分割成块

现在我已经写了一个块的处理,但我不知道如何做每个块的操作。我认为,由于#TYPE *的不断回报,正则表达式操作将是最佳选择。

#TYPE Lorem.Text.A 
... 
#TYPE Lorem.Text.B 
... 
#TYPE Lorem.Text.C 
... 

UPDATE

该解决方案已经从节约的所有部分在一个文件中的所有部分保存为独立的文件,并将它们压缩和解压缩成zip文件改变。这个zip文件是由python读取并进一步分析的。如果有人会对这个解释信息感兴趣,我会更新这个问题。

@Padraic的回答对旧课程最有帮助。

回答

2

你可以使用一个GROUPBY假设该部分通过启动#TYPE线划定:

from itertools import groupby, chain 


def get_sections(fle): 
    with open(fle) as f: 
     grps = groupby(f, key=lambda x: x.lstrip().startswith("#TYPE")) 
     for k, v in grps: 
      if k: 
       yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE 

你可以得到每节为你迭代:

In [13]: cat in.txt 
#TYPE Lorem.Text.A 
first 
#TYPE Lorem.Text.B 
second 
#TYPE Lorem.Text.C 
third 

In [14]: for sec in get_sections("in.txt"): 
    ....:  print(list(sec)) 
    ....:  
['#TYPE Lorem.Text.A\n', 'first\n'] 
['#TYPE Lorem.Text.B\n', 'second\n'] 
['#TYPE Lorem.Text.C\n', 'third\n'] 

如果没有其他行以#然后单独将足以在startswith使用,有没有在你的模式复杂,所以它不是一个真正的正则表达式的用例。这也只是将一段文件一次不存储到整个文件中。

如果你没有前导空白,唯一的地方#出现是TYPE之前可能就足够了就叫GROUPBY:

from itertools import groupby, chain 


def get_sections(fle): 
    with open(fle) as f: 
     grps = groupby(f) 
     for k, v in grps: 
      if k: 
       yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE 

如果有一些元数据在一开始,你可以使用dropwhile跳过线直到我们打#Type,然后就组:

from itertools import groupby, chain, dropwhile 


def get_sections(fle): 
    with open(fle) as f: 
     grps = groupby(dropwhile(lambda x: not x.startswith("#"), f)) 
     for k, v in grps: 
      if k: 
       yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE 

演示:

In [16]: cat in.txt 
meta 
more meta 
#TYPE Lorem.Text.A 
first 
#TYPE Lorem.Text.B 
second 
second 
#TYPE Lorem.Text.C 
third 

In [17]: for sec in get_sections("in.txt"): 
      print(list(sec)) 
    ....:  
['#TYPE Lorem.Text.A\n', 'first\n'] 
['#TYPE Lorem.Text.B\n', 'second\n', 'second\n'] 
['#TYPE Lorem.Text.C\n', 'third\n'] 
+0

我会检查你的建议。 –

+0

@AdrianZ ..它肯定会工作,并避免在存储器中存储多个数据副本,如果你使用。阅读与re.split你将存储在内存中的数据的两个完整副本,如果您的文件很大可能不可能 –

+0

它看起来非常好,我喜欢不浪费内存的想法。现在我没有从打印输出中获得输出,但我会继续测试一下,然后返回结果。 –

-1
根据新行字符

待办事项分裂存在前#TYPE

chunks = re.split(r'\n(?=#TYPE\b *)', f.read()) 

例子:

>>> import re 
>>> s = '''#TYPE Lorem.Text.A 
... 
#TYPE Lorem.Text.B 
... 
#TYPE Lorem.Text.C 
...''' 
>>> re.split(r'\n(?=#TYPE *)', s) 
['#TYPE Lorem.Text.A\n...', '#TYPE Lorem.Text.B\n...', '#TYPE Lorem.Text.C\n...'] 
>>> 
+0

不应该以'^'而不是'\ n'开头吗?如果第一行匹配,我相信您的解决方案将不起作用。 – zondo

+0

@zondo是否希望第一行被分割为'['','#TYPE']'?而且也没有必要使用'^' –

+0

它在我的测试用例中看起来不错。只是有点混乱,但没关系。我也要测试其他答案。我很好奇哪一个对性能影响最小。 –

相关问题