
ca.というファイルがあります。 2列と3列(範囲の始まりと終わり)の値に基づいて17000行を抽出する必要があります。
File_1.txt
NC_018723.3 88839 102219
NC_018723.3 156206 160651
NC_018723.3 160885 165615
NC_018723.3 178410 191119
NC_018723.3 226179 242932
NC_018723.3 243929 310071
NC_018723.3 384020 413475
範囲を含む2番目のファイルがあります。
File_2.txt
8410001 8420000
8420001 8430000
28550001 28560000
28560001 28570000
111910001 111920000
111920001 111930000
209310001 209320000
209320001 209330000
209330001 209340000
2列と3列の範囲がfile_2.txtの範囲に属するfile_1.txtから行を抽出する方法を探しています。
どんなアイデアでも大いに感謝します。
答え1
TXR不明瞭な音声解決策。
まず、file_1.txt
実際に次の範囲に属するいくつかの範囲ケースが追加されましたfile_2.txt
。
NC_018723.3 88839 102219
NC_018723.3 156206 160651
NC_018723.3 160885 165615
NC_018723.3 178410 191119
NC_018723.3 226179 242932
NC_018723.3 243929 310071
NC_018723.3 384020 413475
FOO_1 8420001 8430000
FOO_2 8430000 8440000
FOO_3 8430000 8440000
FOO_4 209310001 209320001
FOO_5 209310001 209320000
FOO_6 209310002 209320000
FOO_7 209310002 209319999
ランニング:
$ txr soln.tl
FOO_1 8420001 8430000
FOO_5 209310001 209320000
FOO_6 209310002 209320000
FOO_7 209310002 209319999
コードは次の場所にありますsoln.tl
。
(defvarl rtree [tree nil to])
(defun add-range (tree range)
(tree-insert tree range))
(defun lookup-range (tree range)
(let* ((iter (tree-begin tree (from range)))
(node (tree-next iter))
(found (if node (key node))))
(if (and found
(>= (from range) (from found))
(<= (to range) (to found)))
found)))
(awk
(:inputs "file_2.txt")
(t (fconv i i) (add-range rtree [f 0]..[f 1])))
(awk
(:inputs "file_1.txt")
(t (fconv - i i)
(if (lookup-range rtree [f 1]..[f 2])
(prn))))
ここでのアプローチは、バイナリ検索ツリーを使用して範囲を保存することですfile_2.txt
。
TXR Lispには範囲タイプがあります:アクセサfrom
とto
。 REPLでこれを閲覧できます。
1> 10..20
#R(10 20)
2> (typeof *1)
range
3> (from *1)
10
4> (to *1)
20
soln.tl
プログラムでは、式は[tree nil to]
新しいバイナリ検索ツリーを構成します。nil
空にしておくことがto
重要な機能です。to
範囲フィールドにアクセスする関数であることに注意してください。このツリーに範囲オブジェクトを配置し、to
そのオブジェクトのフィールドにキーを設定します。
関数がlookup-range
最も複雑です。入力範囲が与えられると、その範囲がツリーに格納された範囲内に含まれるかどうかを決定します。tree-begin
順番にツリーナビゲーションを開始しますが、入力範囲フィールドto
より低いキー(つまりフィールド)を持つすべてのノードを無視するために使用されます。from
つまり、検索範囲のフィールドto
よりも大きい最も低いフィールドを持つノードを探しています。from
ノードが見つかったら、単純なネストされたテストを適用してそれを確認します。
関数定義の後には2つの式があります(awk ..)
。最初のawk
プロセスはfile_2.txt
ツリーハッシュを埋めます。 Awkfconv
演算子は、フィールドを整数に変換し、[f 0]..[f 1]
そこから範囲オブジェクトを構築するために使用されます。
2番目の{awk ...)
ジョブは、file_1.txt
範囲検索と一致するレコード印刷を処理します。
バランスバイナリツリーは範囲に使用されるため、file_2.txt
サイズが大きくなる可能性があります。
でフィールドを変更したため、スペースは出力に保存されませんfconv
。 Awk では、フィールドに割り当てると、出力フィールド区切り文字を使用してフィールドを連結してレコードイメージを再計算します。
スペースを維持するために、awk
2番目のスペースをこのように変更できます。ローカル変数を導入し、それを使用して記録されたrecsave
値を保持します(クラシックAwkと同様)。rec
$0
(awk
(:inputs "file_1.txt")
(:let recsave)
(t (set recsave rec)
(fconv - i i)
(if (lookup-range rtree [f 1]..[f 2])
(prn recsave))))