3

以下に示すように2つのファイルがあります。

ファイル1(タブ区切り):

A1 someinfo1 someinfo2 someinfo3
A1 someinfo1 someinfo2 someinfo3
B1 someinfo1 someinfo2 someinfo3
B1 someinfo1 someinfo2 someinfo3

ファイル2(タブ区切り):

A1 newinfo1 newinfo2 newinfo3
A1 newinfo1 newinfo2 newinfo3
B1 newinfo1 newinfo2 newinfo3
B1 newinfo1 newinfo2 newinfo3

ファイル1から2行(A1とA1で始まる行)とファイル2から2行(A1とA1で始まる行)を一緒に読みたいです。より明確にするために、2つの要件があります。

1)同じファイルから2行を読み取る
2)他のファイルから同じ2行を読み取ります。  

正確には、4行を一緒に読みたい(2つのファイルから2行連続(各ファイルから2行))。

オンラインで検索したところ、2行を一緒に読み取るコードを取得できましたが、1つのファイルからしか取得できませんでした。

open(File1)をfile1として使用します。
        itertools.izip_longest(* [file1] * 2)のline1、line2の場合:

また、2つのファイルのそれぞれから1行を次のように読み取ることもできました。

for i、(line1、line2)in enumerate(itertools.izip(f1、f2)):
        line1、line2を印刷します

しかし、私は次のようにsthを実行したいと思います。

擬似コード:

file1のline1、line2、file2のline_1およびline_2の場合:
              line1とline2を比較する
              line1とline_1を比較します
              line2とline_1を比較します
              line2とline_2を比較します

私は解決策が線形時間のものになることを望んでいます。すべてのファイルの行数は同じで、最初の列(プライマリID)はファイル内の連続する行で同じであり、他のファイルは同じ順序に従います(上記の例を参照)。

ありがとう。

4

4 に答える 4

6

これはどう:

with open('a') as A, open('b') as B:
    while True:
        try:
            lineA1, lineA2, lineB1, lineB2 = next(A), next(A), next(B), next(B)
            # compare lines
            # ...
        except StopIteration:
            break
于 2013-01-16T23:39:05.580 に答える
1
>>> from itertools import izip
>>> with open("file1") as file1, open("file2") as file2:
...     for a1, a2, b1, b2 in izip(file1, file1, file2, file2):
...         print a1, a2, b1, b2
... 
A1   someinfo1     someinfo2    someinfo3
A1   someinfo1     someinfo2    someinfo3
A1   newinfo1     newinfo2    newinfo3
A1   newinfo1     newinfo2    newinfo3

B1   someinfo1     someinfo2    someinfo3
B1   someinfo1     someinfo2    someinfo3
B1   newinfo1     newinfo2    newinfo3
B1   newinfo1     newinfo2    newinfo3

このように行数をパラメータ()にすることができますn

for lines in izip(*[file1]*n+[file2]*n):

n*2これで、行は要素を持つタプルになります

于 2013-01-17T00:08:16.377 に答える
1

これらをどのように組み合わせることができるか見てみましょう。初め:

with open(File1) as file1:
    for line1,line2 in itertools.izip_longest(*[file1]*2):

さて、forループを外すと、一度に2行ずつのイテレータがfileありますよね?したがって、についても同じことができますfile2。そして、あなたはzipそれらを一緒にすることができます:

with open(File1) as file1, open(File2) as file2:
    f1 = itertools.izip_longest(*[file1]*2)
    f2 = itertools.izip_longest(*[file2]*2)
    for i,((f1_line1, f1_line2), (f2_line1, f2_line2)) in enumerate(itertools.izip(f1,f2)):
        # do stuff

しかし、あなたは本当にこれをしたくありません。

izip_longest(*[file1]*2)まず、ほとんどの人は、それがペアでグループ化されていることを直感的に読んで理解していません。それを関数としてまとめます。実際、関数を自分で作成することすらしないでください。itertoolsのドキュメントgrouperからすぐに取り出してください。

だから今、それは:

with open(File1) as file1, open(File2) as file2:
    pairs1 = grouper(2, file1)
    pairs2 = grouper(2, file2)
    for i,((f1_line1, f1_line2), (f2_line1, f2_line2)) in enumerate(itertools.izip(f1,f2)):
        # do stuff

次に、パターンマッチングはかっこいいかもしれませんが、複雑な式の真ん中で分解するネストされたパターンは少し多すぎます。flattenそれでは、それを分割して、itertoolsドキュメントから再度借用して、ネストを解除しましょう。

with open(File1) as file1, open(File2) as file2:
    pairs1 = grouper(2, file1)
    pairs2 = grouper(2, file2)
    zipped_pairs = itertools.izip(pairs1, pairs2)
    for i, zipped_pair in enumerate(zipped_pairs):
        f1_line1, f1_line2, f2_line1, f2_line2 = flatten(zipped_pair)
        # do stuff

このソリューションの利点は、抽象的で一般的であるということです。つまり、後で5行または3ファイルのグループが必要であると判断した場合、変更は明らかです。

このソリューションの欠点は、抽象的で一般的であるということです。つまり、具体的な同等のソリューションを実行するほど単純ではない可能性があります。(たとえば、sのzipペアを上げなかった場合、結果を出す必要はありません。)grouperflatten

于 2013-01-16T23:39:48.753 に答える
0

これは、同じid列を持つ任意の数の連続した行を許可する一般化です。

from itertools import groupby, izip, product

getid = lambda line: line.partition(" ")[0] # first space-separated column
same_id = lambda lines: groupby(lines, key=getid)

with open(File1) as file1, open(File2) as file2:
     for (id1, lines1), (id2, lines2) in izip(same_id(file1), same_id(file2)):
         if id1 != id2: 
            # handle error here
            break
         # compare all possible combinations
         for a, b in product(lines1, lines2): 
             compare(a, b)
于 2013-01-17T00:08:25.170 に答える