2つのソートされたリストに一意の要素が含まれていることを確認する最速の方法

2つのソートされたリストに一意の要素が含まれていることを確認する最速の方法

A2つのソートされたファイルがあり、BサイズがAはるかに大きいですB。たとえば、Aは100GB、Bは50MBです。欲しい早くの行Bがに含まれていることを確認し、一致するAものがあれば停止します。現在、この目的のためのPythonスクリプトがありますが、他のプロセスに対して何千回もプロセスを繰り返す必要がある場合は遅くなりますB

答え1

を使用すると、fifoを使用してcomm最初の一致でスクリプトを返すことができます。head

#!/bin/bash -e 

[ -p tmpfifo ] || mkfifo tmpfifo
comm -12 A B | head -n1 >tmpfifo &

# If this wc is zero, no matches.  Otherwise, a match was found. 
# You can use this directly in the script, echo it, 
# change the script exit value, or however else you need to use it.
wc -l tmpfifo 

現在、これはバックグラウンドで通信を続けており、PID殺す権利(殺人ではなく$!与えるもの)を見つけるのに苦労しています。これが実行中の唯一の通信であると確信している場合は機能しますが、他の通信が実行されている場合は危険です。 headcommkillall

答え2

AWKを使用してファイルを解析できます。最初は、大きなファイルを分割したり、Aをmemに保存してBを実行して、各行をmemのAと比較したいと思いました。しかし、私の考えでは、AWKがあなたが探しているものかもしれません。

http://www.linuxjournal.com/article/8913プライマーです。

http://forums.devshed.com/unix-help-35/compare-two-files-using-awk-or-sed-425150.htmlファイル比較について話します。私は今Linuxを使用していません。それともテストしてみましょう。

愚かなhttp://www.gnu.org/software/gawk/manual/html_node/index.html

答え3

ファイルがソートされている場合は、Join(1)またはmerge(1)を使用してかなり効率的に作業できます。 head -1出力は最初の行で停止し、終了時にSIGPIPEを使用してコマンドの残りの部分を終了します。

さらに、より大きなファイルAでuniq(1)を使用すると、問題のサイズを減らすことができます。これは別の行セットにまとめられ、Bファイルのリストと比較できます。

もう1つの可能性は、次のようにPythonスクリプトを調整することです。

For each B file:
    Read in each line
    Add the file name to a list of files keyed on a hash of the line 

Loop through the A file:
    Look up each line in the dictionary
    Output the file name when a match is found.

「B」ファイル内の他の行数が多いとメモリが大量に消費されるため、実用的でもそうでない場合もあります。偽の肯定を排除するための後処理が気に入らない場合は、この段階でハッシュのみを保存してメモリ消費量を減らすことができます。

3番目のアプローチは、すべてのデータをデータベースにロードして接続することです。ただし、これを行うと、データを取得するオーバーヘッドが発生し、大きすぎる可能性があります。適切なインデックスを使用すると、実際の一致クエリが非常に高速になり、すべてのBファイルを一度に確認できます。

Create table A (
       TextLine varchar (100) -- or whatever length you need
)

Create table B (
       TextLine varchar (100)
      ,Filename varchar (20)
)

Alter table B
  add constraint PK_B
      primary key (TextLine, FileName)


select distinct B.FileName
  from A
  join B
    on a.TextLine = B.TextLine

答え4

grep -F -x -f B A | head -n 1

これはgrepのよく知られている機能ではありませんが、各パターンを1行に配置して、単一のファイルを介して複数のパターンを渡すことができます。これは-F、正確な文字列を見つけるために一緒に使用するときに最も便利です(を使用すると、-E効果はで区切られた複数のパターンと同じです|)。

まだベンチマークはしていませんが、A前処理なしでできるだけ早く出てほしいです。

関連情報