как удалить одинаковые слова в двух файлах?

У меня есть два текстовых файла.

file1.txt содержит:

gedit
google chrome
git
vim
foo
bar

file2.txt содержит:

firefox
svn
foo
vim

Как написать скрипт, который при выполнении (с аргументами file1.txt и file2.txt) проверяет дублирование текста в каждой строке (Я имею в виду, что он должен обрабатываться построчно), удаляет дублированный текст в обоих файлах.

Таким образом, после обработки файлы file1.txt и file2.txt должны иметь следующее содержимое:

gedit
google chrome
git
bar
firefox
svn

Обратите внимание, что foo и vim удалены из обоих файлов.

Любое руководство?


person Santosh Kumar    schedule 23.06.2012    source источник
comment
зачем 2 файла с одинаковым содержимым? насколько велики эти файлы, могут ли они поместиться в память, когда оба открыты одновременно? + что вы уже пробовали?   -  person Aprillion    schedule 23.06.2012
comment
Попробуйте использовать структуру данных set() для поиска дубликатов. docs.python.org/library/sets.html   -  person user590028    schedule 23.06.2012
comment
@deathApril Предположим, я переустанавливаю Ubuntu. Итак, я получаю список пакетов с помощью команды dpkg --get-selection (file1.txt), и есть еще один список, сделанный мной самостоятельно (file2.txt), этот файл содержит то, что я помню, что я установил. После переустановки Ubuntu я установил программное обеспечение, увидев file2.txt. Теперь необходимо установить оставшееся содержимое обоих файлов. Теперь остальная часть в моем вопросе....   -  person Santosh Kumar    schedule 23.06.2012
comment
Всегда старайтесь думать о правильном типе данных для каждой отдельной задачи. Если это удастся, ваш путь сгладится. Самый простой способ — искать уже существующие типы данных, которые могут соответствовать вашим потребностям (и потребностям внутренних функций): меньше проблем, больше эффективности.   -  person Paul    schedule 23.06.2012
comment
порядок контента имеет значение?   -  person Ashwini Chaudhary    schedule 23.06.2012
comment
@Santosh, тогда ознакомьтесь с моим решением.   -  person Ashwini Chaudhary    schedule 23.06.2012


Ответы (6)


with open('file1.txt','r+') as f1 ,open('file2.txt','r+') as f2:
    file1=set(x.strip() for x in f1 if x.strip())
    file2=set(x.strip() for x in f2 if x.strip())
    newfile=file1.symmetric_difference(file2) #symmetric difference removes those values which are present in both sets, and returns a new set.
    f2.truncate(0) #truncate the file to 0 bytes
    f1.truncate(0)
    f2.seek(0) # to push the cursor back to the starting pointing in the file.
    f1.seek(0)
    for x in newfile:
        f1.write(x+'\n')
        f2.write(x+'\n')

теперь оба файла содержат:

svn
git
firefox
gedit
google chrome
bar
person Ashwini Chaudhary    schedule 23.06.2012
comment
+1 приятный штрих к симметричной разнице (file1 ^ file2) - person Aprillion; 23.06.2012
comment
Что делает set()? - person Santosh Kumar; 05.08.2013
comment
Набор @SantoshKumar возвращает уникальные элементы из итератора/итератора. - person Ashwini Chaudhary; 05.08.2013

Вы сохраните отфильтрованный файл как третий файл?

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

Def func(File a, File b):
 for i in a: 
    for j in b:
      if a[i]==b[j]:
        copy and move
      endif
     endfor
  endfor
person doniyor    schedule 23.06.2012
comment
Нет, я хочу, чтобы дубликаты были удалены из обоих файлов (модификация в обоих файлах). - person Santosh Kumar; 23.06.2012

если я правильно понимаю ваш вопрос, это должно быть легко.

alist = []
for i in ifile1:
    alist.append(i)

for i in ifile2:
    if i in alist:
        alist.remove(i)
    else:
        alist.append(i)

for i in alist:
    print i
person lucemia    schedule 23.06.2012
comment
set будет лучшим способом сделать это, если у вас есть большое количество данных. - person lucemia; 23.06.2012

если файлы достаточно малы, чтобы поместиться в память, это сделает работу:

with open("file1.txt", "r") as f1, open("file2.txt", "r") as f2:
    # create a set from the bigger file 
    result = set(x.strip() for x in f1.readlines())
    # remove duplicates or add unique values from 2nd file
    for line in f2:
        line = line.strip()
        if line in result:
            result.remove(line)
        else:
            result.add(line)
result = "\n".join(result)

# for debug, don't replace original files
with open("file1_out.txt", "w") as f1, open("file2_out.txt", "w") as f2:
    f1.write(result)
    f2.write(result)

# if not inside a function, free memory explicitly  
del result 
person Aprillion    schedule 23.06.2012

Для Python 2.7+, где был представлен Counter

>>> from collections import Counter
>>> file_1 = ['gedit','google chrome','git','vim','foo','bar']
>>> file_2 = ['firefox','svn','foo','vim']
>>> de_dup = [i for i,c in Counter(file_1+file_2).itertimes() if c == 1]
>>> de_dup
['svn', 'git', 'bar', 'gedit', 'google chrome', 'firefox']
person Burhan Khalid    schedule 23.06.2012

Начнем с имен входных файлов:

files = ('raz.txt','dwa.txt')

И некоторые вспомогательные функции. Это генератор, который читает все слова из файла,

def read(filename):
    with open(filename) as f:
        for line in f:
            if len(line)>0:
                yield line.strip()

И это записывает последовательность в файл.

def write(filename, lines):
    with open(filename, 'w') as f:
        f.write('\n'.join(lines))

Итак, давайте создадим два генератора — по одному для каждого входного файла.

words = [read(filename) for filename in files]

Затем давайте преобразуем этот список генераторов в список наборов

wordSets = map(set, words)

Теперь у нас есть список из двух наборов, содержащих только уникальные слова из каждого файла.

Давайте создадим еще один набор, содержащий слова, присутствующие во всех входных файлах, путем пересечения их наборов:

commonWords = set.intersection(*wordSets)

И время для перезаписи.

for filename in files:

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

Давайте создадим генератор считывателей, а затем прочитаем все это в память, обернув его list():

    lines = list(read(filename))

а затем записать слова обратно в данный файл по порядку, но только если они не в commonWords

    write(filename, (word for word in lines if word not in commonWords))

Вход:

раз.txt

gedit
google chrome
git
vim
foo
bar

два.txt

firefox
svn
foo
vim

Выход:

раз.txt

gedit
google chrome
git
bar

два.txt

firefox
svn

Дубликаты были удалены из обоих.

person Kos    schedule 23.06.2012
comment
извините за -1, но я считаю этот пост нечитаемым - # comments might help - person Aprillion; 23.06.2012