仅根据 Python 中的某些列改进 运行 重复数据删除列表的时间
Improving Run Time for deduping lists based on only certain columns in Python
我有两个 csv 文件。我正在尝试删除某些列匹配的所有行。我想我会使用 Python 中的列表来执行此操作。我以为它会很快,但 运行 太慢了。
我只想比较前 3 列,因为后 2 列不可靠。然而,我想导出最后两列。
示例:
A = [
(Jack, Smith, New York, USA, 100),
(Jim, Doe, Cleveland, UK, 200),
(Frank, Johnson, Chicago, USA, 300)
]
B = [
(Jack, Smith, New York, United States, blank),
(Jerry, Smith, Cleveland, USA, blank),
(Frank, Johnson, Chicago, America, blank)
]
Matched List = [
(Jack, Smith, New York, USA, 100)
(Frank, Johnson, Chicago, USA, 300)
]
Desired List = [
(Jim, Doe, Cleveland, UK, 200)
]
所以我写了两个嵌套的For循环来比较两个列表并删除匹配项。但是,我的列表 A 大约有 50,000 行,列表 B 有 600,000 行。这需要 3.5 小时。我需要 运行 它在一组 300,000 和 4,000,000 行上;但是在看到这需要多长时间后 运行 几天。
这是两个 For 循环(我正在比较第 0、7、9 和 10 列。)
for Acquisition_row in Acquisition_list[:]:
for Leads_row in Leads_list:
if (Acquisition_row[0] == Leads_row[0]) and (Acquisition_row[7] == Leads_row[7]) and (Acquisition_row[9] == Leads_row[9]) and (Acquisition_row[10] == Leads_row[10]):
try:
Acquisition_list.remove(Acquisition_row)
Leads_list.append(Acquisition_row)
except:
print("Error!")
有什么办法可以加快速度吗?有更好的方法吗?我应该使用不同的编程语言吗?也许将这些上传到 SQL 数据库中的临时 table 并使用 SQL?
谢谢!
@kindall 正确地建议 set()
或 dict
跟踪您到目前为止所看到的内容。
def getKey(row):
return (row[0], row[7], row[9], row[10])
# create a set of all the keys you care about
lead_keys = {getKey(r) for r in Leads_rows}
# save this off due to reverse indexing gyration
len_ac_list = len(Acquisition_list)
for i, ac_row in enumerate(Acquisition_list[::-1]):
ac_key = getKey(ac_row)
if ac_key in lead_keys: ## this look up is O(1)
index = len_ac_list - i - 1
Acquisition_list.pop(index)
Leads_list.append(ac_row)
## maybe: lead_keys.add(ac_key)
好处是:在创建键集时,您只需迭代 Leads_list 一次(我为此选择 Leads_list 是因为它是更大的列表,因此会为您节省更多时间);并且您查找 Acquisition_list 需要常数时间,O(1) 而不是 O(n),其中 n 是 len(Leads_list).
在您的原始设置中,最坏的情况下,您正在执行 (n*m) 或 (300000*4000000) 次操作,这是……一吨。使用 set
s,你只会做 (n+m) 或 (30000+4000000),这是......少得多。就像少了 300,000 倍。这就是 1.2 万亿事物与 .000004 万亿(400 万)事物之间的差异。
我有两个 csv 文件。我正在尝试删除某些列匹配的所有行。我想我会使用 Python 中的列表来执行此操作。我以为它会很快,但 运行 太慢了。
我只想比较前 3 列,因为后 2 列不可靠。然而,我想导出最后两列。
示例:
A = [
(Jack, Smith, New York, USA, 100),
(Jim, Doe, Cleveland, UK, 200),
(Frank, Johnson, Chicago, USA, 300)
]
B = [
(Jack, Smith, New York, United States, blank),
(Jerry, Smith, Cleveland, USA, blank),
(Frank, Johnson, Chicago, America, blank)
]
Matched List = [
(Jack, Smith, New York, USA, 100)
(Frank, Johnson, Chicago, USA, 300)
]
Desired List = [
(Jim, Doe, Cleveland, UK, 200)
]
所以我写了两个嵌套的For循环来比较两个列表并删除匹配项。但是,我的列表 A 大约有 50,000 行,列表 B 有 600,000 行。这需要 3.5 小时。我需要 运行 它在一组 300,000 和 4,000,000 行上;但是在看到这需要多长时间后 运行 几天。
这是两个 For 循环(我正在比较第 0、7、9 和 10 列。)
for Acquisition_row in Acquisition_list[:]:
for Leads_row in Leads_list:
if (Acquisition_row[0] == Leads_row[0]) and (Acquisition_row[7] == Leads_row[7]) and (Acquisition_row[9] == Leads_row[9]) and (Acquisition_row[10] == Leads_row[10]):
try:
Acquisition_list.remove(Acquisition_row)
Leads_list.append(Acquisition_row)
except:
print("Error!")
有什么办法可以加快速度吗?有更好的方法吗?我应该使用不同的编程语言吗?也许将这些上传到 SQL 数据库中的临时 table 并使用 SQL?
谢谢!
@kindall 正确地建议 set()
或 dict
跟踪您到目前为止所看到的内容。
def getKey(row):
return (row[0], row[7], row[9], row[10])
# create a set of all the keys you care about
lead_keys = {getKey(r) for r in Leads_rows}
# save this off due to reverse indexing gyration
len_ac_list = len(Acquisition_list)
for i, ac_row in enumerate(Acquisition_list[::-1]):
ac_key = getKey(ac_row)
if ac_key in lead_keys: ## this look up is O(1)
index = len_ac_list - i - 1
Acquisition_list.pop(index)
Leads_list.append(ac_row)
## maybe: lead_keys.add(ac_key)
好处是:在创建键集时,您只需迭代 Leads_list 一次(我为此选择 Leads_list 是因为它是更大的列表,因此会为您节省更多时间);并且您查找 Acquisition_list 需要常数时间,O(1) 而不是 O(n),其中 n 是 len(Leads_list).
在您的原始设置中,最坏的情况下,您正在执行 (n*m) 或 (300000*4000000) 次操作,这是……一吨。使用 set
s,你只会做 (n+m) 或 (30000+4000000),这是......少得多。就像少了 300,000 倍。这就是 1.2 万亿事物与 .000004 万亿(400 万)事物之间的差异。