2013-07-09 65 views
0

我想從兩個獨立的文件,如採取文字:Python的文本文件操作

File 1: 
000892834  13.663  0.098  0.871  0.093  0.745  4.611  4795 

File 2: 
892834 4916 75 37 4857 130 128 4795 4.61 -0.09 0 0 

,並得到一個輸出,如:

892834  13.663  0.098  0.871  0.093  0.745  4.611  4795 
892834  4916  4795  -0.09 

我有一些代碼,似乎接近解決方案:

filter_func_1 = lambda x: x >= 15 
filter_func_2 = lambda x: (5777 + 100) > x > (5777 - 100) 
mergedData = defaultdict(list) 
with open('Table1_Karoff.txt') as file_1, open('Table7_Pinsonneault.txt') as file_2, open('Processed_Data.txt', 'w') as outfile: 
     for line_1 in file_1: 
      splt_file_1 = line_1.split() 
      if filter_func_1(splt_file_1[1]): 
       mergedData[splt_file_1[0].lstrip('0')].append(line_1) 
     for line_2 in file_2: 
       splt_file_2 = line_2.split() 
     Data = map(itemgetter(0, 1, 8, 9), line_2) 
      if filter_func_2(splt_file_2[1]): 
       mergedData[splt_file_2[0]].append([' '.join(map(str, i)) for i in Data]) 
     for k in mergedData: 
      if len(mergedData[k]) == 2: 
       outfile.write("\n".join(mergedData[k]) + "\n")   
     return outfile 

一下這個代碼是「應該」做的就是創建兩種過濾我們在lambda操作符中,將每行中的某個索引與lambda函數進行比較,看看它是否爲true,如果是,則將整行附加到列表中以便輸出。它還從文件1中的第一個數字的開頭剝離'000',並檢查以確保兩個文件中都存在相同的第一個數字。

我的問題是:

1)file_1編號(即第一個數字)不正確都在0的從中剝離,儘管據我所知,代碼應該這樣做。它輸出爲00892834,因此只刪除第一個0.

2)添加過濾器後,根本沒有數據會寫入新文件,並且當我檢查是否已正確創建line.split時一個新的列表,它沒有,這意味着沒有數據要過濾,因爲splt_file_#輸入中沒有數據。這對我來說很奇怪,我不明白這是怎麼可能發生的。我通過在最後添加一個應該寫出splt_file_1和splt_file_2列表的writeline來測試列表創建,但是它沒有吐出任何東西。 3)由於我需要的值不能在列表中從文件2中按順序調用(我只需要索引0,1,8,9),我試圖映射然後格式化數據,但是這會給出一個索引範圍問題,這是可以理解的,因爲我在上面#2中的問題。

我需要任何幫助,我可以在刪除這些錯誤,我不知道我的代碼是錯誤的,或者如果我只是失去了一些東西,謝謝任何幫助。

+0

你能在上面的代碼中修復你的縮進嗎? –

+0

@MichaelPratt當然!對不起,我沒有注意到 – ImmortalxR

+1

輸入文件中是否有多行?如果是這樣,你是否介意在讀取這兩個文件後將它們讀入內存中以進行內存匹配?你對這些輸入行的順序有什麼限制嗎? – Gijs

回答

1

對不起,不糾正你的解決方案,但有時不同的採取也可以有所幫助。如果我理解正確,這將是我的代碼。

file_1_data = dict() 
file_2_data = dict() 
for filename, data in [('infile1.txt', file_1_data), ('infile2.txt', file_2_data)]: 
with open(filename) as f: 
    for line in f: 
     split_line = line.split()  
     first_int = int(split_line[0]) 
     rest_floats = [float(f) for f in split_line[1:]] 
     data[first_int] = rest_floats 

現在你有兩個文件,其中鍵是int字典,這樣你可以比較的,和值是浮動的名單。之後這很容易。

def filter_1(x): 
return x > 1 

def filter_2(x): 
return 4 < x < 100000 

with open('outfile.txt', 'wb') as outfile: 
for key in file_1_data: 
    if key in file_2_data: 
     #write a record, the first one 
     data_to_write = [str(f) for f in file_1_data[key] if filter_1(f)]  
     record = ' '.join([str(key)] + data_to_write) + '\n' 
     outfile.write(record) 
     #second one, do filtering here 
     data_to_write = [str(f) for f in file_2_data[key] if filter_2(f)] 
     record = ' '.join([str(key)] + data_to_write) + '\n' 
     outfile.write(record) 

希望它有幫助。我認爲我的觀點是:不要擔心有點冗長或者過於簡單化,只要簡單一點,避免重複自己就可以了。祝你好運。

+0

是的輸出需要看起來和我放在OP中一模一樣,如果你的意思是匹配,那麼就必須要有ID號碼 – ImmortalxR

+0

對不起,但我讀得越多,我越理解你的OP。什麼是過濾?代碼中的內容與您發佈的示例數據不符。而且每個輸入文件中只有一行,並且它們在第一列中是否總是有相等的整數? – Gijs

+0

我想我的其他評論解決這個問題:) – ImmortalxR

1

您將字符串傳遞給filter_func_1filter_func_2,然後將它們與lambda表達式中的整數進行比較。但是當你比較數字和字符串時,比較是退化的:數字總是被認爲是在字符串之前(這是特定於實現的;我假設CPython的行爲)。所以你的第一個lambda總是會返回True和第二個False。因此,它們不能用作代碼中的過濾器。

您需要將您傳遞的字符串轉換爲整數或浮點數,例如:

filter_func_1 = lambda x: float(x) >= 15 

或者您可以在將它傳遞給過濾器之前轉換您的輸入。無論哪種情況,您都應該考慮在輸入無法轉換爲數字類型時要執行的操作。

轉換爲數字類型也將擺脫前導0 s。它可能會或可能不會幫助解決第二個問題,但無論如何,只有在對代碼的這部分進行更改之後,才能得到期望的結果。

+0

謝謝你的洞察力,對於我如何以你提到的方式進行轉換有什麼幫助? – ImmortalxR

+1

你會想要將int()或float()應用於每一段數據(參見[here](http://docs.python.org/2/library/functions.html)) )。如果你喜歡使用所有的浮動,你可以寫下如下內容:'splt_file_1 = map(float,line_1.split())'。 – Alp

+0

如果我將它應用於代碼,它工作得很好,但我只需要拉出文件2的某些部分,我正在使用itemgetter來嘗試執行此操作,這就是我所擁有的:\t splt_file_2 = map(float,line_2 .split())\t splt_2_Data = map(itemgetter(0,1,8,9),splt_file_2)這給了我一個錯誤,但浮動沒有getitem屬性,我怎麼能解決這個問題? – ImmortalxR