繁体   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