Удаление строк в Python после того, как я напишу их - PullRequest
0 голосов
/ 05 августа 2010

Хорошо, вот мой существующий код:

////////////// = []
for line in datafile:
    splitline = line.split()
    for item in splitline:
        if not item.endswith("JAX"):
            if item.startswith("STF") or item.startswith("BRACKER"):
                //////////.append( item )


for line in //////////
    print /////////////
   /////////// +=1
    for t in//////
        if t in line[:line.find(',')]:
            line = line.strip().split(',')
           ///////////////write(','.join(line[:3]) + '\n') 
            break

/////////////.close()
/////////////close()
///////////.close()

Я хочу провести дальнейшую оптимизацию. Файл действительно большой. Я хотел бы удалить из него строки, которые были сопоставлены после того, как они были сопоставлены и записаны в небольшой файл, чтобы сократить время, необходимое для поиска в большом файле. Любые предложения о том, как я должен идти по этому поводу?

Ответы [ 2 ]

1 голос
/ 05 августа 2010

Вы не можете удалять строки в текстовом файле - для этого потребуется переместить все данные после удаленной строки вверх, чтобы заполнить пробел, и это будет крайне неэффективно.

Один из способов сделать это - записать временный файл со всеми строками, которые вы хотите сохранить в bigfile.txt, а после завершения обработки удалить bigfile.txt и переименовать временный файл, чтобы заменить его.

В качестве альтернативы, если bigfile.txt достаточно мал, чтобы поместиться в памяти, вы можете прочитать весь файл в список и удалить строки из списка, а затем записать список обратно на диск.

Я бы также догадался из вашего кода, что bigfile.txt - это что-то вроде CSV-файла. Если это так, то может быть лучше преобразовать его в файл базы данных и использовать SQL для запроса. Python поставляется со встроенным модулем SQLite, и для большинства других баз данных имеются сторонние библиотеки.

0 голосов
/ 06 августа 2010

Как я сказал в комментарии, для меня не похоже, что размер "bigfile" должен замедлять скорость, с которой увеличивается счетчик. Когда вы перебираете такой файл, Python просто читает по одной строке за раз по порядку.

Оптимизация, которую вы можете выполнить в этот момент, зависит от того, насколько велики строки matchedLines, и как соотносятся строки matchedLines с текстом, который вы просматриваете.

Если matchedLines велико, вы можете сэкономить время, выполнив «поиск» только один раз:

for line in completedataset:
   text = line[:line.find(',')] 
   for t in matchedLines:
        if t in text:
            line = line.strip().split(',')
            smallerdataset.write(','.join(line[:3]) + '\n') 
            break

В моих тестах поиск находился примерно в 300 наносекунд, поэтому, если длина строки matchedLines составляет несколько миллионов единиц, у вас есть лишняя секунда.

Если вы ищете точные совпадения, а не совпадения подстрок, вы можете ускорить процесс, используя набор:

matchedLines = set(matchedLines)
for line in completedataset:
    target = line[:line.find(',')]
    ## One lookup and you're done!
    if target in matchedLines:
        line = line.strip().split(',')
        smallerdataset.write(','.join(line[:3]) + '\n') 

Если целевые тексты, которые не соответствуют друг другу, имеют тенденцию выглядеть совершенно иначе, чем те, которые делают (например, большинство целей являются случайными строками, а matchedLines представляет собой набор имен), а все matchedLines имеют длину выше определенной , вы можете попытаться стать действительно умным, проверив подстроки. Предположим, что все строки соответствий имеют длину не менее 5 символов ...

def subkeys(s):
    ## e.g. if len(s) is 7, return s[0:5], s[1:6], s[2:7].
    return [s[i:i+5] for i in range(len(s) + 1 - 5)]

existing_subkeys = set()
for line in matchedLines:
    existing_subkeys.update(subkeys(line))

for line in completedataset:
    target = line[:line.find(',')]
    might_match = False
    for subkey in subkeys(target):
        if subkey in existing_subkeys:
            might_match = True
            break
    if might_match:
        # Then we have to do the old slow way.
        for matchedLine in matchedLines:
            if matchedLine in target:
                # Do the split and write and so on.

Но действительно легко перехитрить себя, пытаясь делать подобные вещи, и это зависит от того, как выглядят ваши данные.

...