2011-08-14 48 views
1

鑑於: 兩個csv文件(每個1.8 MB):AllData_1,AllData_2。每條約8000行。每行由8列組成。 [txt_0,txt_1,txt_2,txt_3,txt_4,txt_5,txt_6,txt_7,txt_8]Python 2列表比較優化

目標: 基於匹配txt_0的(或,AllData_1 [0] == AllData_2),比較的內容接下來的4列爲這些單獨的行。如果數據不相等,則將每一組數據的整行放入基於列不同的列表中,並將列表保存到輸出文件。如果txt_0是一個數據集,但不是另一個,則直接將其保存到輸出文件。

實施例:

AllData_1行x包含:A1,B2,C3,D4,E5,F6,G7,H8] AllData_2列Y包括:[A1,B2,C33C,d44d,E5,F6 ,G7,H8]

程序將保存所有的行x和y的對應ListCol2和ListCol3名單。所有比較完成後,列表將保存到文件中。

如何讓我的代碼更快或將代碼更改爲更快的算法?

i = 0 
x0list = [] 
y0list = [] 
col1_diff = col2_diff = col3a_diff = col3b_diff = col4_diff = [] 

#create list out of column 0 
for y in AllData_2: 
    y0list.append(y[0]) 

for entry in AllData_1: 
    x0list.append(entry[0]) 
    if entry[0] not in y0list: 
     #code to save the line to file... 

for y0 in AllData_2: 
    if y0[0] not in x0list: 
     #code to save the line to file... 

for yrow in AllData_2: 
    i+=1 

    for xrow in AllData_1: 
     foundit = 0 
     if yrow[0] == xrow[0] and foundit == 0 and (yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]): 
      if yrow[1] != xrow[1]: 
       col1_diff.append(yrow) 
       col1_diff.append(xrow) 
       foundit = 1 

      elif yrow[2] != xrow[2]: 
       col2_diff.append(yrow) 
       col2_diff.append(xrow) 
       foundit = 1 

      elif len(yrow[3]) < len(xrow[3]): 
       col3a_diff.append(yrow) 
       col3a_diff.append(xrow) 
       foundit = 1 

      elif len(yrow[3]) >= len(xrow[3]): 
       col3b_diff.append(yrow) 
       col3b_diff.append(xrow) 
       foundit = 1 

      else: 
       #col4 is actually a catch-all for any other differences between lines if [0]s are equal 
       col4_diff.append(yrow) 
       col4_diff.append(xrow) 
       foundit = 1 
+0

也許這可以幫助http://stackoverflow.com/questions/744256/reading-huge-file-in-python –

+1

使用裝置不列出了會員測試。 – katrielalex

+0

'foundit == 0'應該做什麼?它總是如此,因爲在測試之前'foundit'被設置爲0。 –

回答

1

如果你能指望在一個給定的文件中沒有兩行有列0相同的數據,就可以顯著的幾個dict小號提高你的代碼。相反,線

x0list.append(entry[0]) 
y0list.append(y[0]) 

,你會使用:

x0dict[entry[0]] = entry 
y0dict[y[0]] = y 

初始化x0dicty0dict{}後。然後,而不是通過數據的兩個成套再次循環,您可以在http://stardict.sourceforge.net/Dictionaries.php下載的只是一個循環:

for x0, xrow in x0dict: 
    if x0 in y0dict: 
     yrow = y0dict[x0] 
     # Do the col{1,2,3,4}_diff stuff here 

作爲獎勵,在第二和第三循環的not in的工作原理相同。


(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]) 

可以用更好看的

yrow[1:5] != xrow[1:5] 

來代替,你的代碼代表現在,i從未使用過,但如果你需要這個數字,它最終只是說i = len(AllData_2),因爲它只在每次運行中增加一次通過AllData_2循環。


最後,您的foundit變量當前沒有任何用處。它僅用於在將其設置爲0後立即用foundit == 0來控制流量,以便始終評估爲True並將其設置爲無效。

+0

我不明白爲什麼你不能直接比較'yrow [1:5]'和'xrow [1:5]'嗎?切片是序列,它比較元素明智... –

+0

@Karl哎呀,目前的項目是在coffeescript,我習慣了不能正常工作。編輯。 –

+0

非常感謝您的回覆。我有幾個後續問題。對於大多數比較,我正在尋找與第一列匹配的行。但是,我照顧了不必要的我(不太多的速度增益)和foundit比較(〜25%的速度增益)。再次感謝! – Mark

1

右上方,你可以做得更小。

y0list = [] 
for y in AllData_2: 
    y0list.append(y[0]) 

只是說

y0list = [y[0] for y in AllData_2] 

的詳細方式,你可以在內置的比較使用。 的下面

(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]) 

可以表示爲

yrow[1:] != xrow[1:] 

這是更不容易複製/粘貼錯誤。

爲了加快速度,您可以避免進行O(n ** 2)比較。既然你只關心第一列元素是否相同,你可以通過第一個元素來捆綁它們。

index = {} 
for yrow in AllData_2: 
    key = yrow[0] 
    list = index.get(key) 
    if list is None: 
     list = [] 
     index[key] = list 
    list.append(yrow) 

for xrow in AllData_1: 
    list = index.get(xrow[0]) 
    if list is None: continue 
    for yrow in list: 
     # Do all your comparison here 
+0

非常感謝您的幫助,尤其是O(n ** 2)代碼。捆綁使工作變得很好,除了現在缺少兩個初始比較。 x [0]不能在all_y和y [0]中不能all_x(與上面原始代碼不同)被添加? – Mark