[英]Improving python performance in comparing two lists
我有兩個電子郵件地址列表:new_emails.tsv和old_emails.tsv
old_emails.tsv中有大約1000萬行,new_emails.tsv中有大約150萬行。 我想創建一個新的.tsv文件,該文件位於old_emails.tsv但不在new_emails.tsv中。 原因是因為在后面的步驟中我需要從我的MySQL數據庫中刪除那組電子郵件。
這兩個文件有不同的標題,即:
new_emails.tsv has ['ACCTNUM', 'CUST_ID', 'EMAIL', 'CODE']
old_emails.tsv has ['ACCTNUM', 'EMAIL', 'OPTION']
所以為了解決這個問題,我將兩個文件中的電子郵件字段拉到自己的列表中,然后比較列表,轉換為集合,找出差異(重載' - '運算符)。 現在,在exclusion_emails列表中的電子郵件列表中,我需要使用此列表從old_emails.tsv中提取行,並將這些行放在名為exclusion_emails.tsv的新文件中。 但是,將我的exclusion_emails列表轉換為從old_emails.tsv中獲取的行列表是一個非常繁瑣的過程。 有沒有辦法改善這種表現? 我的完整代碼在這里:
import csv
def csv_to_list(file):
output_list = []
with open(file, 'rb') as f_new_emails:
reader = csv.reader(f_new_emails, delimiter='\t')
for line in reader:
output_list.append(line)
return output_list
new_emails_list = csv_to_list('new_emails.tsv')
old_emails_list = csv_to_list('old_emails.tsv')
# Get the index for the email field
def get_email_index(alist):
if 'EMAIL' in alist:
return alist.index('EMAIL')
elif 'email' in alist:
return alist.index('email')
s_new_emails = set([row[get_email_index(new_emails_list[0])] for row in new_emails_list])
s_old_emails = set([row[get_email_index(old_emails_list[0])] for row in old_emails_list])
exclusion_emails = [email for email in (s_old_emails - s_new_emails)]
# print("%s emails in the new list" % len(new_emails_list))
# print("%s emails in the old list" % len(old_emails_list))
# print("%s emails in the old list but not in the new list" % len(exclusion_emails))
# Creating the new file
exclusion_rows = []
operations = 0
with open('exclusions.tsv', 'wb') as tsvfile:
writer = csv.writer(tsvfile, delimiter='\t')
for email in exclusion_emails:
for row in old_emails_list:
operations += 1
if email in row:
writer.writerow(row)
break
print(len(exclusion_rows))
任何幫助,將不勝感激!
這需要很長時間,因為您將每個排除的電子郵件與每個舊電子郵件記錄進行比較(750萬次,1000萬次是75 TRILLION循環迭代...)。
有三個主要的改進。
首先,索引不能為每條記錄更改,因此不要為每次迭代重新計算它們,並且因為每個列表中的第一個條目是標題,所以從搜索中排除它(如果在輸出文件中隨機輸出多個標題,如果例如舊的和新的電子郵件標題字段大寫不同):
new_email_index = get_email_index(new_emails_list[0])
old_email_index = get_email_index(old_emails_list[0])
s_new_emails = set([row[new_email_index] for row in new_emails_list[1:]])
s_old_emails = set([row[old_email_index] for row in old_emails_list[1:]])
並且在構建最終記錄列表時,old_email_index將非常有用。
將排除項保留為一組,
exclusion_emails = s_old_emails - s_new_emails
當你構建exclusions.tsv時,遍歷舊的聲明列表,這樣你就可以獲取電子郵件地址(使用你上面保存的索引而不是每次重新計算),
with open('exclusions.tsv', 'wb') as tsvfile:
writer = csv.writer(tsvfile, delimiter='\t')
for row in old_emails_list[1:]:
print str(row[old_email_index])
if row[old_email_index] in exclusion_emails:
writer.writerow(row)
最后,exclusion_rows最后是一個空列表,因為你的代碼實際上並沒有向exclusion_rows添加任何東西,所以不要讓它打印的長度為0會讓你感到困惑。
這個awk版本只是為了顯示O(n)的想法; 如果它運行得足夠快,請在python中重寫它。
awk -F"\t" 'NR==FNR { a[$3]=1; next; };
$2 && !a[$2] {print} ' new_emails.tsv old_emails.tsv > new.tsv
說明:
a
電子郵件 a
,則寫入其記錄 (如果可能的話,比較所用的時間,並告訴我們......)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.