2016-03-03 57 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

它在我的測試用例中看起來不錯。只是有點混亂,但沒關係。我也要測試其他答案。我很好奇哪一個對性能影響最小。 –

相關問題