Python 2列出了比较优化

时间:2011-08-14 00:45:44

标签: python performance list compare

给定: 两个csv文件(每个1.8 MB):AllData_1,AllData_2。每个约有8,000行。每行包含8列。 [txt_0,txt_1,txt_2,txt_3,txt_4,txt_5,txt_6,txt_7,txt_8]

目标: 基于txt_0(或AllData_1 [0] == 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 个答案:

答案 0 :(得分:1)

如果您认为给定文件中没有两行在第0列中具有相同的数据,则可以使用少量dict来显着改善您的代码。而不是行

x0list.append(entry[0])
y0list.append(y[0])

你会使用:

x0dict[entry[0]] = entry
y0dict[y[0]] = y
x0dicty0dict初始化为{}

。然后,不是再次遍历两个完整的数据集,而是可以遍历其中一个词:

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变量目前没有用处。它仅用于在设置为0后立即使用foundit == 0来控制流量,因此始终将其评估为True并将其设置为无效。

答案 1 :(得分:1)

在顶部,您可以将其缩小很多。

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