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
범위가 포함된 두 번째 파일이 있습니다.
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
노드가 발견되면 간단한 중첩 테스트를 적용하여 이를 확인합니다.
함수 정의 뒤에는 두 개의 표현식이 있습니다 (awk ..)
. 첫 번째 awk
프로세스는 file_2.txt
트리 해시를 채웁니다. Awk fconv
연산자는 필드를 정수로 변환하고 [f 0]..[f 1]
그로부터 범위 개체를 구성하는 데 사용됩니다.
두 번째 {awk ...)
작업은 file_1.txt
범위 검색 및 일치하는 레코드 인쇄를 처리합니다.
균형 이진 트리는 범위에 사용되므로 file_2.txt
크기가 커질 수 있습니다.
로 필드를 수정했기 때문에 공백은 출력에 보존되지 않습니다 fconv
. Awk에서는 필드에 할당하면 출력 필드 구분 기호를 사용하여 필드를 연결하여 레코드 이미지를 다시 계산합니다.
공백을 유지하기 위해 awk
두 번째 공백을 이렇게 변경할 수 있습니다. 우리는 지역 변수를 도입하고 이를 사용하여 기록된 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))))