Python 2 списки сравнения оптимизации - PullRequest
1 голос
/ 14 августа 2011

Принимая во внимание: Два CSV-файла (1,8 МБ каждый): AllData_1, AllData_2. Каждый с ~ 8000 строк. Каждая строка состоит из 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 - это один набор данных, но не другой, сохраните его непосредственно в выходном файле.

Пример:

Строка x AllData_1 содержит: [a1, b2, c3, d4, e5, f6, g7, h8] Строка y AllData_2 содержит: [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 ]

1 голос
/ 14 августа 2011

Справа от верха вы можете сделать это намного меньше.

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
1 голос
/ 14 августа 2011

Если вы можете ожидать, что никакие две строки в данном файле не будут иметь одинаковые данные в столбце 0, вы можете значительно улучшить свой код с помощью нескольких 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, и установка этого значения не имеет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...