Python 2 列表比较优化
给定的情况:
有两个csv文件(每个文件大小为1.8 MB):AllData_1和AllData_2。每个文件大约有8000行。每一行包含8列数据。
目标:
根据txt_0的匹配(也就是说,AllData_1的第一列等于AllData_2的第一列),比较这两行的接下来的4列内容。如果这些数据不相等,就把每组数据的整行放到一个列表里,列表是根据不同的列来分类的,并把这些列表保存到输出文件中。如果txt_0在一个数据集中存在,但在另一个数据集中不存在,那么就直接把这个数据保存到输出文件中。
举个例子:
AllData_1的某一行x包含:[a1, b2, c3, d4, e5, f6, g7, h8],而AllData_2的某一行y包含:[a1, b2, c33c, d44d, e5, f6, g7, h8]
程序会把行x和行y都保存到对应的列表ListCol2和ListCol3中。在所有比较完成后,这些列表会被保存到文件里。
我该如何让我的代码更快,或者把我的代码改成更快的算法呢?
i = 0
x0list = []
y0list = []
col1_diff = col2_diff = col3a_diff = col3b_diff = col4_diff = []
#create list out of column 0
for y in AllData_2:
y0list.append(y[0])
for entry in AllData_1:
x0list.append(entry[0])
if entry[0] not in y0list:
#code to save the line to file...
for y0 in AllData_2:
if y0[0] not in x0list:
#code to save the line to file...
for yrow in AllData_2:
i+=1
for xrow in AllData_1:
foundit = 0
if yrow[0] == xrow[0] and foundit == 0 and (yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4]):
if yrow[1] != xrow[1]:
col1_diff.append(yrow)
col1_diff.append(xrow)
foundit = 1
elif yrow[2] != xrow[2]:
col2_diff.append(yrow)
col2_diff.append(xrow)
foundit = 1
elif len(yrow[3]) < len(xrow[3]):
col3a_diff.append(yrow)
col3a_diff.append(xrow)
foundit = 1
elif len(yrow[3]) >= len(xrow[3]):
col3b_diff.append(yrow)
col3b_diff.append(xrow)
foundit = 1
else:
#col4 is actually a catch-all for any other differences between lines if [0]s are equal
col4_diff.append(yrow)
col4_diff.append(xrow)
foundit = 1
2 个回答
一开始,你可以把这个缩小很多。
y0list = []
for y in AllData_2:
y0list.append(y[0])
这只是说得比较啰嗦的一种表达方式。
y0list = [y[0] for y in AllData_2]
而且你可以在内置的比较中使用它。
下面这个
(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4])
可以用
yrow[1:] != xrow[1:]
来表示,这样更不容易出现复制粘贴的错误。
为了让它更快,你可以避免做 O(n**2) 的比较。因为你只关心第一列的元素是否相同,所以你可以根据第一个元素来进行分组。
index = {}
for yrow in AllData_2:
key = yrow[0]
list = index.get(key)
if list is None:
list = []
index[key] = list
list.append(yrow)
for xrow in AllData_1:
list = index.get(xrow[0])
if list is None: continue
for yrow in list:
# Do all your comparison here
如果你能确保在一个文件中,第一列的每一行数据都是不一样的,那么你可以通过使用几个 dict
(字典)来大幅提升你的代码效率。这样,你就不需要像下面这样处理每一行:
x0list.append(entry[0])
y0list.append(y[0])
你可以用下面的方式:
x0dict[entry[0]] = entry
y0dict[y[0]] = y
在初始化 x0dict
和 y0dict
为 {}
之后。然后,你就不需要再遍历所有的数据,而只需遍历其中一个字典:
for x0, xrow in x0dict:
if x0 in y0dict:
yrow = y0dict[x0]
# Do the col{1,2,3,4}_diff stuff here
另外,你在第二和第三个循环中使用的 not in
也能正常工作。
这一行:
(yrow[1] != xrow[1] or yrow[2] != xrow[2] or yrow[3] != xrow[3] or yrow[4] != xrow[4])
可以换成更好看的:
yrow[1:5] != xrow[1:5]
目前你的代码中,i
这个变量没有被用到,但如果你需要这个计数,它其实和直接写 i = len(AllData_2)
是一样的,因为在遍历 AllData_2
的循环中,它每次只增加一次。
最后,你的 foundit
变量现在没有任何用处。它只是用来控制流程的,像 foundit == 0
这样的判断,设置为0后总是会返回 True
,所以设置它并没有实际效果。