簡體   English   中英

在比較兩個列表時提高python性能

[英]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

說明:

  • 第1行保存new_emails em array a電子郵件
  • 第2行如果old_emails的(非空)電子郵件不在a ,則寫入其記錄

(如果可能的話,比較所用的時間,並告訴我們......)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM