0

私は3つのテキストファイルを持っています:

ファイルA:

13  abc
123 def
234 ghi
1234    jkl
12  mno

ファイル B:

12  abc
12  def
34  qwe
43  rty
45  mno

ファイルC:

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]
4

1 に答える 1

3

A1B1、およびC1を 2 番目の列で並べ替えるだけの場合、これは簡単です。

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))

John Clements が指摘しているように、A1 だけで 3 つすべてをセットにする必要さえないので、代わりに次のようにすることができます。

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_everseenitertoolsread_file

于 2013-03-29T20:22:55.153 に答える