提高python比较两个列表的性能

2024-06-16 08:43:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个电子邮件地址列表:新的_电子邮件.tsv而且很老_电子邮件.tsv你知道吗

老城区大约有1000万排_电子邮件.tsv纽约大约有150万排_电子邮件.tsv. 我想创建一个新的.tsv文件,其中包含旧版本中的电子邮件地址_电子邮件.tsv但不是在纽约_电子邮件.tsv. 这是因为在后面的步骤中,我需要从MySQL数据库中删除这组电子邮件。你知道吗

这两个文件有不同的头,即:

new_emails.tsv has ['ACCTNUM', 'CUST_ID', 'EMAIL', 'CODE']
old_emails.tsv has ['ACCTNUM', 'EMAIL', 'OPTION']

为了解决这个问题,我将两个文件中的email字段拉到它们自己的列表中,然后比较列表,转换为集合,并找到差异(重载的“-”运算符)。由于电子邮件列表现在在排除电子邮件列表中,我需要使用此列表从旧列表中提取行_电子邮件.tsv并将这些行放入名为exclusion的新文件中_电子邮件.tsv. 然而,将我的电子邮件列表转换为从旧邮件中提取的行列表_电子邮件.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))

任何帮助都将不胜感激!你知道吗


Tags: csvthein列表newforindextsv
2条回答

这需要很长时间,因为你要将每一封被排除的电子邮件与每一封旧的电子邮件记录进行比较(750万乘以1000万等于75万亿次循环迭代…)。你知道吗

主要有三个改进。你知道吗

首先,索引不能为每个记录更改,因此不要为每个迭代重新计算索引,因为每个列表中的第一个条目是标题,所以将其从搜索中排除(如果新旧电子邮件标题字段的大写方式不同,则输出文件中可能会随机出现多个标题):

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:]])

在构建最终记录列表时,旧的电子邮件索引将非常有用。你知道吗

把除外责任作为一个整体

exclusion_emails = s_old_emails - s_new_emails

当你建造除外责任.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\u rows在末尾是一个空列表,因为您的代码实际上没有向exclusion\u 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行保存新邮件的电子邮件em数组a
  • 第2行如果旧电子邮件的(非空)电子邮件不在a中,写下它的记录

(如果可能,比较所用的时间,并向我们展示…)

相关问题 更多 >