Найти общий список между файлами
У меня есть три текстовых файла:
FiLea:
13 abc
123 def
234 ghi
1234 jkl
12 mno
FILEB:
12 abc
12 def
34 qwe
43 rty
45 mno
fileC:
12 abc
34 sdg
43 yui
54 poi
54 def
Я хотел бы видеть, что все значения во 2-м столбце совпадают между файлами. Следующий код работает, если 2-й столбец уже отсортирован. но если 2-й столбец не отсортирован, как мне отсортировать 2-й столбец и сравнить файлы?
fileA = open("A.txt",'r')
fileB = open("B.txt",'r')
fileC = open("C.txt",'r')
listA1 = []
for line1 in fileA:
listA = line1.split('\t')
listA1.append(listA)
listB1 = []
for line1 in fileB:
listB = line1.split('\t')
listB1.append(listB)
listC1 = []
for line1 in fileC:
listC = line1.split('\t')
listC1.append(listC)
for key1 in listA1:
for key2 in listB1:
for key3 in listC1:
if key1[1] == key2[1] and key2[1] == key3[1] and key3[1] == key1[1]:
print "Common between three files:",key1[1]
print "Common between file1 and file2 files:"
for key1 in listA1:
for key2 in listB1:
if key1[1] == key2[1]:
print key1[1]
print "Common between file1 and file3 files:"
for key1 in listA1:
for key2 in listC1:
if key1[1] == key2[1]:
print key1[1]
1 ответ
Если вы просто хотите отсортировать A1
, B1
, а также C1
по второму столбцу это легко:
listA1.sort(key=operator.itemgetter(1))
Если ты не понимаешь itemgetter
, это тоже самое:
listA1.sort(key=lambda element: element[1])
Тем не менее, я думаю, что лучшим решением будет просто использовать set
:
setA1 = set(element[1] for element in listA1)
setB1 = set(element[1] for element in listB1)
setC1 = set(element[1] for element in listC1)
Или, проще говоря, не создавайте списки в первую очередь; сделай это:
setA1 = set()
for line1 in fileA:
listA = line1.split('\t')
setA1.add(listA[1])
В любом случае:
print "Common between file1 and file2 files:"
for key in setA1 & setA2:
print key
Чтобы еще больше упростить его, вы, вероятно, захотите сначала преобразовать повторяющиеся элементы в функции:
def read_file(path):
with open(path) as f:
result = set()
for line in f:
columns = line.split('\t')
result.add(columns[1])
return result
setA1 = read_file('A.txt')
setB1 = read_file('B.txt')
setC1 = read_file('C.txt')
И тогда вы сможете найти дополнительные возможности. Например:
def read_file(path):
with open(path) as f:
return set(row[1] for row in csv.reader(f))
Как отмечает Джон Клементс, вам даже не нужно, чтобы все три из них были сетами, а только А1, поэтому вы можете вместо этого сделать это:
def read_file(path):
with open(path) as f:
for row in csv.reader(f):
yield row[1]
setA1 = set(read_file('A.txt'))
iterB1 = read_file('B.txt')
iterC1 = read_file('B.txt')
Единственное другое изменение, которое вам нужно, это то, что вы должны позвонить intersection
вместо использования &
оператор, так:
for key in setA1.intersection(iterB1):
Я не уверен, что это последнее изменение на самом деле улучшение. Но в Python 3.3 единственное, что вам нужно сделать, это изменить return set(…)
в yield from (…)
Я бы, наверное, так и сделал. (Даже если файлы огромны и имеют множество дубликатов, так что это стоило производительности, я бы просто придерживался unique_everseen
от itertools
рецепты по всему read_file
вызовы.)