Разделить элемент списка в python по пользовательскому индексу

У меня есть список под названием:

Фёрстсеквенсетосплит

и он содержит один элемент, который представляет собой последовательность ДНК, скажем:

'АТТТАГКТА'

Я могу легко вернуть длину этого элемента, чтобы пользователь знал, что он имеет длину 10 символов, и затем я хочу, чтобы пользователь сказал, что он хочет извлечь символы индекса, скажем [0:6], и чтобы затем создать два элемента в новом списке. Первый элемент содержит символы определяемого пользователем индекса, за которым следует вопросительный знак, заменяющий другие символы, которые не были извлечены, а второй элемент имеет инверсию.

Итак, чтобы проиллюстрировать, что я хочу, если пользователь сказал, что хочет [0:5], вы получите новый список со следующими элементами:

['АТТТТ?????', '?????ACGTA']

Все это часть гораздо более крупной проблемы, когда у меня есть набор последовательностей ДНК в формате FASTA («>Sequence1/nATTTTACGTA», «>Sequence2/nATTGCACGTA» и т. д.), и я хочу, чтобы пользователь мог выбрать последовательность на основе его идентификатор и чтобы эта последовательность была разделена на основе предопределенного ввода и называлась Sequence2a и Sequence2b ('>Sequence1a/n?????ACGTA', '>Sequence1b/nATTTT?????''>Sequence2/ nATTGCACGTA' и др.). В настоящее время я решил проблему, напечатав имена последовательностей, позволив пользователю выбрать одну для объединения, извлекая только последовательность (без идентификатора), а затем, как только я решу проблему, показанную выше, я создам новый список с новыми элементами.

Поскольку я новичок (и я уверен, что это уже очевидно!) Я был бы признателен за любые объяснения приведенного кода. Большое спасибо за любую возможную помощь, которую вы можете оказать

Мой код до сих пор:

import sys
import re

#Creating format so more user friendly

class color:
   PURPLE = '\033[95m'
   CYAN = '\033[96m'
   DARKCYAN = '\033[36m'
   BLUE = '\033[94m'
   GREEN = '\033[92m'
   YELLOW = '\033[93m'
   RED = '\033[91m'
   BOLD = '\033[94m'
   UNDERLINE = '\033[4m'
   END = '\033[0m'


fileName = raw_input("Give the name of the Fasta file you wish to divide up  ")
# i.e TopTenFasta

#Reading in the sequences splitting them by the > symbol
in_file = open(fileName,"r")
sequences = in_file.read().split('>')[1:] 
in_file.close() 


#Putting all these sequences into a list
allSequences = []
for item in sequences:
    allSequences.append(item)

#Letting you know how many sequences there are in total
NumberOfSequences = len(allSequences)
print color.BOLD + "The Number of Sequences in this list is: " +color.END, NumberOfSequences

#Returning the names of the IDs to allow you to decide which ones to split
SequenceIds = []
for x in allSequences:
    SequenceIds.append(x[0:10])

print color.BOLD + "With the following names: " + color.END, "\n", "\n".join(SequenceIds)

#-----------------------Starting the Splice ------------------------------------
#-----------------------------------------------------------------------------
#------------------------------------------------------------------------------



#Choosing the sequence you wish to splice 
FirstSequenceToSplitID = raw_input(color.BOLD + "Which sequence would you like to splice  " + color.END)

#Seeing whether that item is in the list
for x in SequenceIds:
    if FirstSequenceToSplitID == x:
        print "valid input"

FirstSequenceToSplit = []

#making a new list (FirstSequenceToSplit) and putting into it just the sequence (no ID)
for listItem in allSequences:
    if listItem[0:10]==FirstSequenceToSplitID:
        FirstSequenceToSplit.append(listItem[11:])

#Printing the Length of the sequence to splice
for element in FirstSequenceToSplit:
    print color.BOLD + "The Length of this sequence is" + color.END, len(element)

person PaulBarr    schedule 10.04.2014    source источник
comment
Привет, я не включил свой код, так как хотел сосредоточиться на главном вопросе своего поста, но я отредактировал его, чтобы показать, что я сделал до сих пор, вероятно, он очень длинный, так как я только недавно начал кодировать, так что извиняюсь!   -  person PaulBarr    schedule 10.04.2014


Ответы (2)


Я бы использовал понимание и почтовый индекс. Я прокомментировал код, но не стесняйтесь спрашивать, если что-то неясно.

my_str = 'ATTTTACGTA'

# This loop will check that 
#  - the casting to int is ok
#  - there are only two numbers inputted
#  - stop >= start
#  - start > 0
#  - stop < len(my_str)
while True:
    try:
        start, stop = map(int, raw_input(
            'Please enter start and stop index separated by whitespace\n').split())
        if stop < start or start < 0 or stop > len(my_str):
            raise ValueError
        break
    except ValueError:
        print 'Bad input, try again'


# Loop over all chars, check if the current index is inside range(start, stop).
# If it is, add (char, '?') to the array, if not, add ('?', char) to the array.
#
# This would give you an array of something like this:
# [('?', 'A'), ('?', 'T'), ('T', '?'), ('T', '?'), ('?', 'T'), ('?', 'A'),
#  ('?', 'C'), ('?', 'G'), ('?', 'T'), ('?', 'A')]
#
# By using zip(*array), we unpack each element, and saves the first indexes as
# one list, and the second indexes as another, giving you a list like this:
#
# [('?', '?', 'T', 'T', '?', '?', '?', '?', '?', '?'),
#  ('A', 'T', '?', '?', 'T', 'A', 'C', 'G', 'T', 'A')]

chars = zip(*((c, '?') if i in range(start, stop) else ('?', c)
              for i, c in enumerate(my_str)))

# ''.join is used to concencate all chars into two strings
my_lst = [''.join(s) for s in chars]
print my_lst

Пример вывода:

Please enter start and stop index separated by whitespace
4
Bad input, try again
Please enter start and stop index separated by whitespace
5 4
Bad input, try again
Please enter start and stop index separated by whitespace
e 3
Bad input, try again
Please enter start and stop index separated by whitespace
4 5
['????T?????', 'ATTT?ACGTA']
person Steinar Lima    schedule 10.04.2014
comment
Большое вам спасибо, я собираюсь внедрить это в свой код и спрошу, как только я это сделаю, спасибо за вашу помощь! Это помогает мне учиться, а также решать мои проблемы! - person PaulBarr; 10.04.2014
comment
Я пытался заставить его работать, но на данный момент я получаю список с ['ATTTTACGTA', '?'] независимо от моих входных данных. Мне также пришлось изменить код: если остановить ‹ start или start ‹ 0 или остановить › len(my_str): поднять ValueError, поскольку длина списка равна 1 (1 элемент), имеет ли значение, что я делаю это в списке, а не чем строка? - person PaulBarr; 11.04.2014
comment
Я решил эту проблему, сохранив элемент списка в виде строки, поэтому код не работал в самом списке, спасибо! - person PaulBarr; 11.04.2014

Это выражение будет работать:

[ c[0:n] + '?' * (len(c)-n), '?' * n + c[n:] ]
person Malvolio    schedule 10.04.2014
comment
@PaulBarr Просто чтобы уточнить, c - это ваша строка, n - это индекс, по которому вы хотите разбить. - person photoionized; 10.04.2014
comment
Спасибо, можно ли как-нибудь разделить два индекса, например [2:6]? - person PaulBarr; 10.04.2014
comment
@PaulBarr, если вам нужны три строки, измените приведенное выше следующим образом: [ c[0:n] + '?' * (len(c)-n), '?' * n + c[n:m] + '?' * (len(c)-m), '?' * m + c[m:] ]. Это довольно простая математика. - person photoionized; 10.04.2014
comment
вместо '?' * (len(c)-n), вы делаете что-то вроде следующего, {0:09d}".format(str) - person AdriVelaz; 10.04.2014
comment
Я имею в виду еще две строки, т.е. имеющие ['???TT?????','ATT??ACGTA'], извиняюсь за основные вопросы, но я пока не смог решить это самостоятельно. - person PaulBarr; 10.04.2014
comment
@PaulBarr Хорошо, тогда это просто среднее выражение в приведенном выше комментарии, '?' * n + c[n:m] + '?' * (len(c)-m) по сути, это просто создание фрагмента строки между индексами n и m, а затем добавление правильного количества '?' к строке для заполнения. - person photoionized; 10.04.2014