строки в файле не совпадают со строкой в наборе

#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 ГБ, который не может быть загружен в память (ОЗУ), использование этого счетчика приведет к ошибке памяти, верно?