Я хочу получить все oneKmer
, которых нет в in.txt
.in.txt
сортируется в том же порядке, что и oneKmer
в столбце 0.
Это должно быть выполнимо в O (N) вместо O (N ^ 2), поскольку оба списка находятся в одном порядке.
Как я могу это написать?
import csv
import itertools
tsvfile = open('in.txt', "r")
tsvreader = csv.reader(tsvfile, delimiter = " ")
for i in itertools.product('ACTG', repeat = 18):
oneKmer = ''.join(i)
flag = 1
with open(InFile) as tsvfile:
tsvreader = csv.reader(tsvfile, delimiter = " ")
for line in tsvreader:
if line[0] == oneKmer:
flag = 0
break
if flag:
print(oneKmer)
in.txt
:
AAAAAAAAAAAAAAAAAA 1400100
AAAAAAAAAAAAAAAAAC 37055
AAAAAAAAAAAAAAAAAT 70686
AAAAAAAAAAAAAAAAAG 192363
AAAAAAAAAAAAAAAACA 20042
AAAAAAAAAAAAAAAACC 12965
AAAAAAAAAAAAAAAACT 10596
AAAAAAAAAAAAAAAACG 1732
AAAAAAAAAAAAAAAATA 16440
AAAAAAAAAAAAAAAATC 18461
...
Весь файл in.txt
составляет 38 569 002 592 байта с 1 836 020 688 строками.
Ожидаемый результат должен быть (4 ^ 18 - 1 836 020 688) строк строк. Конечно, я буду дополнительно фильтровать их позже в сценарии.
В качестве простого примера предположим, что я хочу напечатать целые числа <16, которых нет в заданном отсортированном списке [3,5,6,8,10,11]
. Результат должен быть [1,2,4,7,9,12,13,14,15]
. Данный список огромен, поэтому я хочу читать его по одному элементу за раз. Поэтому, когда я читаю 3, я знаю, что могу распечатать 1 и 2. Затем пропустить 3 и прочитать следующие 5, теперь я могу распечатать 4 и пропустить 5.
Во-первых, открытие файлов во многих случаях замедляется, поэтому цикл ACTG должен быть включен в файловый цикл. Во-вторых, Stdout работает медленнее, чем вы думаете, поэтому остановите print(onemake)
и выведите напрямую в файл. Возможно, они должны улучшить скорость.
Несколько решений, все из которых обрабатывают суперпоследовательность и подпоследовательность параллельно, используя линейное время и постоянную память.
Используя ваш простой пример:
full = iter(range(1, 16))
skip = iter([3,5,6,8,10,11])
Решение 0: (тот, который я придумал последним, но должен был сделать первым)
s = next(skip, None)
for x in full:
if x == s:
s = next(skip, None)
else:
print(x)
Решение 1:
from heapq import merge
from itertools import groupby
for x, g in groupby(merge(full, skip)):
if len(list(g)) == 1:
print(x)
Решение 2:
for s in skip:
for x in iter(full.__next__, s):
print(x)
for x in full:
print(x)
Решение 3:
from functools import partial
until = partial(iter, full.__next__)
for s in skip:
for x in until(s):
print(x)
for x in full:
print(x)
Решение 4:
from itertools import takewhile
for s in skip:
for x in takewhile(s.__ne__, full):
print(x)
for x in full:
print(x)
Вывод всех решений:
1
2
4
7
9
12
13
14
15
Решение 0 для вашей актуальной проблемы:
import csv
import itertools
with open('in.txt') as tsvfile:
tsvreader = csv.reader(tsvfile, delimiter=' ')
skip = next(tsvreader, [None])[0]
for i in itertools.product('ACTG', repeat=18):
oneKmer = ''.join(i)
if oneKmer == skip:
skip = next(tsvreader, [None])[0]
else:
print(oneKmer)
Небольшое изменение:
import csv
from itertools import product
from operator import itemgetter
with open('in.txt') as tsvfile:
tsvreader = csv.reader(tsvfile, delimiter=' ')
skips = map(itemgetter(0), tsvreader)
skip = next(skips, None)
for oneKmer in map(''.join, product('ACTG', repeat=18)):
if oneKmer == skip:
skip = next(skips, None)
else:
print(oneKmer)
И какие методы задействуют оба списка один раз? Они все едут на велосипеде один раз?
@Галактика Все они. Я только что отредактировал, сделал итераторы full
и skip
.
@Galaxy А теперь я только что добавил самое простое решение, с которого должен был начать :-)
Будут ли методы Solution 1-4 загружать весь список в память? Я не уверен, что python сделает что-то. как ленивая копия или нет.
@Galaxy Нет, все они правильно относятся к ним как к итераторам. См. новое редактирование внизу ответа, показывающее код для вашей реальной проблемы.
Не подскажете, какие методы можно использовать с
csv.reader
без загрузки всего файла? Я не знаком с питоном.