#python #string #set #comparison #equals
#python #строка #набор #сравнение #равно
Вопрос:
У меня есть файл со словом в каждой строке и набор со словами, и я хочу поместить в файл не равные слова из набора, называемого «out». Есть часть моего кода:
def createNextU(self):
print "adding words to final file"
if not os.path.exists(self.finalFile):
open(self.finalFile, 'a').close
fin = open(self.finalFile,"r")
out = set()
for line in self.lines_seen: #lines_seen is a set with words
if line not in fin:
out.add(line)
else:
print line
fin.close()
fout= open(self.finalFile,"a ")
for line in out:
fout.write(line)
но это соответствует только биту реальных равных слов. Я играю с одним и тем же словарем слов, и он добавляет повторяющиеся слова в файл при каждом запуске. Что я делаю не так?? что происходит?? Я пытаюсь использовать компараторы ‘==’ и ‘is’, и у меня тот же результат.
Редактировать 1: я работаю с огромными файлами (finalFile), которые не могут быть полностью загружены в ОЗУ, поэтому я думаю, что мне следует читать файл построчно
Редактировать 2: обнаружена большая проблема с указателем:
def createNextU(self):
print "adding words to final file"
if not os.path.exists(self.finalFile):
open(self.finalFile, 'a').close
out = set()
out.clear()
with open(self.finalFile,"r") as fin:
for word in self.lines_seen:
fin.seek(0, 0)'''with this line speed down to 40 lines/second,without it dont work'''
if word in fin:
self.totalmatches = self.totalmatches 1
else:
out.add(word)
self.totalLines=self.totalLines 1
fout= open(self.finalFile,"a ")
for line in out:
fout.write(line)
Если я помещаю строку lines_seen перед открытием файла, я открываю файл для каждой строки в lines_seen, но скорость увеличивается только до 30 тыс. строк в секунду. С помощью set() у меня в худшем случае получается 200 тыс. строк в секунду, поэтому я думаю, что загружу файл по частям и сравню его с помощью наборов. Есть ли лучшее решение?
Редактировать 3: Готово!
Ответ №1:
fin
это дескриптор файла, с которым вы не можете его сравнить if line not in fin
. Сначала необходимо прочитать содержимое.
with open(self.finalFile, "r") as fh:
fin = fh.read().splitlines() # fin is now a list of words from finalFile
for line in self.lines_seen: #lines_seen is a set with words
if line not in fin:
out.add(line)
else:
print line
# remove fin.close()
Редактировать:
Поскольку lines_seen
это набор, попробуйте создать новый набор со словами из finalFile
then diff the sets?
file_set = set()
with open(self.finalFile, "r") as fh:
for f_line in fh:
new_set.add(f_line.strip())
# This will give you all the words in finalFile that are not in lines_seen.
print new_set.difference(self.lines_seen)
Комментарии:
1. Привет, я попробовал это, и что-то пошло не так, вывод на консоль зависает, не знаю почему, но большое спасибо!!
2. Привет @user3754301 возможно, попробуйте создать новый набор с
finalFile
помощью и дополнить его своим набором слов.3. Я загружаю файл небольшими частями в наборы, которые может содержать ОЗУ, и несколько раз использую ‘difference’, чтобы, наконец, получить уникальные слова. С помощью этого решения я получаю очень высокую производительность. спасибо!!
Ответ №2:
Ваше сравнение, скорее всего, не работает, потому что строки, прочитанные из файла, будут иметь новую строку в конце, поэтому вы сравниваете ‘word n’ с ‘word’. Использование ‘rstrip’ поможет удалить завершающие новые строки:
>>> foo = 'hellon'
>>> foo
'hellon'
>>> foo.rstrip()
'hello'
Я бы также перебирал файл, а не перебирал переменную, содержащую слова, которые вы хотели бы проверить. Если я понял ваш код, вы хотели бы записать все, что находится в self.lines_seen, в self.finalFile, если этого еще нет в нем. Если вы используете ‘если строка не в fin’, как у вас есть, это не будет работать так, как вы ожидаете. Например, если ваш файл содержит:
lineone
linetwo
linethree
и set lines_seen, будучи неупорядоченным, возвращает ‘linethree’, а затем ‘linetwo’, тогда следующее будет соответствовать ‘linethree’, но не ‘linetwo’, потому что объект file уже прочитал его:
with open(self.finalFile,"r" as fin:
for line in self.lines_seen:
if line not in fin:
print line
Вместо этого рассмотрите возможность использования счетчика:
from collections import Counter
linecount = Counter()
# using 'with' means you don't have to worry about closing it once the block ends
with open(self.finalFile,"r") as fin:
for line in fin:
line = line.rstrip() # remove the right-most whitespace/newline
linecount[line] = 1
for word in self.lines_seen:
if word not in linecount:
out.add(word)
Комментарии:
1. Привет !!, сначала спасибо всем за ваши ответы. Если у меня есть огромный файл для открытия, например, 100 ГБ, который не может быть загружен в память (ОЗУ), использование этого счетчика приведет к ошибке памяти, верно?