Вложенные циклы для сравнения 2 файлов - PullRequest
1 голос
/ 20 октября 2011

Я пишу программу для сравнения двух файлов. Для каждой строки в файле 1 я хочу сравнить ее со всеми строками в файле 2, а затем перейти к следующей строке в файле 1. Программа не продолжается в файле 1 после первого попадания. Есть предложения?

Код: Выбрать все

#! /usr/bin/env python

import sys
import fileinput

# Open the two files
f1 = open(sys.argv[1], "r")
f2 = open(sys.argv[2], "r")

for line in f1:
    chrR,chrStart,chrEnd,name,score,strand1,codingStart,codingEnd,itemRbg,blockCount,blockSize,BlockStart = line.strip().split()
    chr = range(int(chrStart), int(chrEnd))
    lncRNA = set(chr)
    for line in f2:
        chrC,clustStart,clustEnd,annote,score,strand = line.strip().split()
        clust = range(int(clustStart), int(clustEnd))
        cluster = set(clust)
        if strand1 == '-':
            if chrR == chrC:
                if strand1 == strand:
                    if cluster & lncRNA:
                         print name,annote,'transcript'
                         continue
                     else:
                         continue
                 continue
        break

Ответы [ 3 ]

3 голосов
/ 16 ноября 2011

После первой строки в f1 вы уже прочитали все строки из файла f2, поэтому for line2 in f2 имеет нулевую итерацию для второй и последующих строк в файле f1, если файл f2 не растет на диске.

#!/usr/bin/env python
import sys

def intersect(r1, r2):
    return r2[0] < (r1[-1]+1) and r1[0] < (r2[-1]+1)

with open(sys.argv[2]) as f2:
     chrC_set, strand_set, clusters = set(), set(), []
     for i, line in enumerate(f2):
         parts = line.split()
         if len(parts) != 6:
            print >>sys.stderr, "%d line has %d parts: %s" % (i, len(parts), line),
            continue
         chrC, clustStart, clustEnd, annote, _, strand = parts
         chrC_set.add(chrC)
         strand_set.add(strand)
         clusters.append((xrange(int(clustStart), int(clustEnd)), annote))

with open(sys.argv[1]) as f1:
     for i, line in enumerate(f1):
         parts = line.split()
         if len(parts) < 6:
            print >>sys.stderr, "%d line has %d parts: %s" % (i, len(parts), line),
            continue
         chrR, chrStart, chrEnd, name, _, strand1 = parts[:6]
         if strand1 == '-' and chrR in chrC_set and strand1 in strand_set:
            lncRNA = xrange(int(chrStart), int(chrEnd))
            for cluster, annote in clusters:
                if intersect(cluster, lncRNA):
                   print name, annote, 'transcript'
1 голос
/ 10 декабря 2011

Тест if strand1 == '-' не зависит от содержимого f2 . Следовательно, вы можете поместить его перед циклом в f2 и запустить проверку всего содержимого f2 , только если текущая строка f1 содержит Strand1 со значением '-'

Учитывая также тот факт, что сначала существует if strand1 == '-', а затем if strand1 == strand, это означает, что вас также интересуют только строки в f2 , в которых прядь имеет значение '-'.

Более того, я воспользовался идеей Дж. Ф. Себастьяна для проверки пересечения двух диапазонов без помощи множеств, а только для проверки границ диапазонов. Однако нет необходимости использовать диапазон или xrange , проверки границ достаточно.

Итак, я предлагаю следующий код в качестве простого улучшения вашего алгоритма:

for line in f1:
    (chrR,chrStart,chrEnd,name,score,strand1,codingStart,codingEnd,
     itemRbg,blockCount,blockSize,BlockStart) = line.strip().split()
    if strand1 == '-':
        s,e = int(chrStart), int(chrEnd)
        for line in f2:
            chrC,clustStart,clustEnd,annote,score,strand = line.strip().split()
            if strand=='-' and chrR == chrC \
               and int(clustStart)<e and s<int(clustEnd):
                print name,annote,'transcript'
        f2.seek(0,0)

.

Однако этот алгоритм (ваш, исправленный) плох: есть полное чтение содержания f2 для каждой строки f1 , содержащей strand1 со значением '-'.

Алгоритм Дж. Ф. Себастьяна намного лучше.
Я немного улучшил его, с идеями, изложенными выше.

with open(sys.argv[2]) as f2:
    clusters = []
    for i, line in enumerate(f2):
        parts = line.split()
        if len(parts) != 6:
            print >>sys.stderr, "%d line has %d parts: %s" % (i,len(parts),line),
            continue
        chrC, clustStart, clustEnd, annote, _, strand = parts
        if strand=='-':
            clusters.append((chrC, int(clustStart), int(clustEnd), annote))

with open(sys.argv[1]) as f1:
    for i, line in enumerate(f1):
        parts = line.split()
        if len(parts) < 6:
            print >>sys.stderr, "%d line has %d parts: %s" % (i,len(parts),line),
            continue
        chrR, chrStart, chrEnd, name, _, strand1 = parts[:6]
        if strand1 == '-':
            for chrC,iclustStart,iclustEnd,annote in clusters:
                if chrR == chrC \
                   and iclustStart<int(chrEnd) and int(chrStart)<iclustEnd:
                    print name, annote, 'transcript'
0 голосов
/ 16 ноября 2011

Вы намеренно делаете «продолжить» после нахождения первого удара. а затем также делать "разрыв" после первой строки.

Тебе не нужно этого делать. Второй цикл продолжится до следующей строки в f2. Затем, когда он дойдет до конца f2 - он перейдет на следующую строку в f1. Если вы действительно хотите проверить каждую строку в f1 относительно каждой строки в f2, тогда все эти продолжения (и разрыв) являются излишними.

Попытка:

for line in f1:
     chrR,chrStart,chrEnd,name,score,strand1,codingStart,codingEnd,itemRbg,blockCount,blockSize,BlockStart = line.strip().split()
    chr = range(int(chrStart), int(chrEnd))
    lncRNA = set(chr)
    for line2 in f2:
            chrC,clustStart,clustEnd,annote,score,strand = line2.strip().split()
            clust = range(int(clustStart), int(clustEnd))
            cluster = set(clust)
            if strand1 == '-':
                    if chrR == chrC:
                            if strand1 == strand:
                                    if cluster & lncRNA:
                                            print name,annote,'transcript'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...