Как удалить дубликаты строк - PullRequest
0 голосов
/ 30 декабря 2018

Я пытаюсь создать простую программу, которая удаляет повторяющиеся строки из файла.Тем не менее, я застрял.Моя цель состоит в том, чтобы в конечном итоге удалить все, кроме 1 дубликата, в отличие от предложенного дубликата.Итак, у меня все еще есть эти данные.Я также хотел бы сделать это так, он принимает то же имя файла и выводит то же имя файла.Когда я пытался сделать имена файлов одинаковыми, он просто выводит пустой файл.

input_file = "input.txt"
output_file = "input.txt"

seen_lines = set()
outfile = open(output_file, "w")

for line in open(input_file, "r"):
    if line not in seen_lines:
        outfile.write(line)
        seen_lines.add(line)

outfile.close()

input.txt

I really love christmas
Keep the change ya filthy animal
Pizza is my fav food
Keep the change ya filthy animal
Did someone say peanut butter?
Did someone say peanut butter?
Keep the change ya filthy animal

Ожидаемый вывод

I really love christmas
Keep the change ya filthy animal
Pizza is my fav food
Did someone say peanut butter?

Ответы [ 6 ]

0 голосов
/ 30 декабря 2018

Только мои два цента, на случай, если вы сможете использовать Python3.Он использует:

  • Многократно используемый Path объект, который имеет удобный метод write_text().
  • OrderedDict в качестве структуры данных для одновременного удовлетворения ограничений уникальности и порядка.
  • Выражение генератора вместо Path.read_text() для экономии памяти.

# in-place removal of duplicate lines, while remaining order
import os
from collections import OrderedDict
from pathlib import Path

filepath = Path("./duplicates.txt")

with filepath.open() as _file:
    no_duplicates = OrderedDict.fromkeys(line.rstrip('\n') for line in _file)

filepath.write_text("\n".join(no_duplicates))
0 голосов
/ 30 декабря 2018

Попробуйте приведенный ниже код, используя списки с str.join и set и sorted:

input_file = "input.txt"
output_file = "input.txt"
seen_lines = []
outfile = open(output_file, "w")
infile = open(input_file, "r")
l = [i.rstrip() for i in infile.readlines()]
outfile.write('\n'.join(sorted(set(l,key=l.index))))
outfile.close()
0 голосов
/ 30 декабря 2018

Я считаю, что это самый простой способ сделать то, что вы хотите:

with open('FileName.txt', 'r+') as i:
    AllLines = i.readlines()
    for line in AllLines:
        #write to file
0 голосов
/ 30 декабря 2018

Строка outfile = open(output_file, "w") усекает ваш файл, что бы вы ни делали.Последующие чтения найдут пустой файл.Моя рекомендация сделать это безопасно - использовать временный файл:

  1. Открыть временный файл для записи
  2. Обрабатывать ввод для нового вывода
  3. Закрыть оба файла
  4. Переместить временный файл к имени входного файла

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

Вот пример использования tempfile.NamedTemporaryFile и блока with, чтобы убедиться, что все закрыто правильно, даже в случае ошибки:

from tempfile import NamedTemporaryFile
from shutil import move

input_file = "input.txt"
output_file = "input.txt"

seen_lines = set()

with NamedTemporaryFile('w', delete=False) as output, open(input_file) as input:
    for line in open(input_file, "r"):
        sline = line.rstrip('\n')
        if sline not in seen_lines:
            output.write(line)
            seen_lines.add(sline)
move(output.name, output_file)

move в конце будет работать правильно, даже если имена входа и выхода совпадают, поскольку output.name гарантированно будет отличаться от обоих.

Обратите внимание, что я убираю новую строку из каждой строки в наборе, поскольку последняя строка может не иметь ее.

Альтернативное решение

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

input_file = "input.txt"
output_file = "input.txt"

with open(input_file) as input:
    unique = set(line.rstrip('\n') for line in input)
with open(output_file, 'w') as output:
    for line in unique:
        output.write(line)
        output.write('\n')

Вы можете сравнить это с

with open(input_file) as input:
    unique = set(line.rstrip('\n') for line in input.readlines())
with open(output_file, 'w') as output:
    output.write('\n'.join(unique))

Вторая версия делает то же самое, но загружает и записывает все сразу.

0 голосов
/ 30 декабря 2018
import os
seen_lines = []

with open('input.txt','r') as infile:
    lines=infile.readlines()
    for line in lines:
        line_stripped=line.strip()
        if line_stripped not in seen_lines:
            seen_lines.append(line_stripped)

with open('input.txt','w') as outfile:
    for line in seen_lines:
        outfile.write(line)
        if line != seen_lines[-1]:
            outfile.write(os.linesep)

Выход:

I really love christmas
Keep the change ya filthy animal
Pizza is my fav food
Did someone say peanut butter?
0 голосов
/ 30 декабря 2018

Проблема в том, что вы пытаетесь записать в тот же файл, из которого читаете.У вас есть как минимум две опции:

Опция 1

Используйте разные имена файлов (например, input.txt и output.txt ).На некотором уровне это проще всего.

Вариант 2

Считать все данные из вашего входного файла, закрыть этот файл, а затем открыть файл для записи.

with open('input.txt', 'r') as f:
    lines = f.readlines()

seen_lines = set()
with open('input.txt', 'w') as f:
    for line in lines:
        if line not in seen_lines:
            seen_lines.add(line)
            f.write(line)

Опция 3

Открыть файл для чтения и записи в режиме r+.В этом случае вы должны быть осторожны, чтобы прочитать данные, которые вы собираетесь обработать, прежде чем писать.Если вы делаете все за один цикл, итератор цикла может потерять отслеживание.

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