split a list of strings at positions they match a different list of strings
<p>I wrote a small program to do the following. I'm wondering if there is an obviously more optimal solution:</p>

<p>1) Take 2 lists of strings. In general, the strings in the second list will be longer than in the first list, but this is not guaranteed</p>

<p>2) Return a list of strings derived from the second list that has removed any matching strings from the first list. The list will therefore contain strings that are &lt;= the length of the strings in the second list.</p>

<p>Below I've displayed a picture example of what I'm talking about:
<a href="http://i.stack.imgur.com/VF1eA.png" rel="nofollow"><img src="http://i.stack.imgur.com/VF1eA.png" alt="basic outline of what should happen"></a></p>

<p>so far I this is what I have. It seems to be working fine, but I'm just curious if there is a more elegant solution that I'm missing. By the way, I'm keeping track of the "positions" of each start and end of the string, which is important for a later part of this program.</p>

<pre><code>def split_sequence(sequence = "", split_seq = "", length = 8):
    if len(sequence) &lt; len(split_seq):
        return [],[]
    split_positions = [0]
    for pos in range(len(sequence)-len(split_seq)):
        if sequence[pos:pos+len(split_seq)] == split_seq and pos &gt; split_positions[-1]:
            split_positions += [pos, pos+len(split_seq)]
    if split_positions[-1] == 0:
        return [sequence], [(0,len(sequence)-1)]
    split_positions.append(len(sequence))
    assert len(split_positions) % 2 == 0
    split_sequences = [sequence[split_positions[_]:split_positions[_+1]] for _ in range(0, len(split_positions),2)]
    split_seq_positions = [(split_positions[_],split_positions[_+1]) for _ in range(0, len(split_positions),2)]
    return_sequences = []
    return_positions = []
    for pos,seq in enumerate(split_sequences):
        if len(seq) &gt;= length:
            return_sequences.append(split_sequences[pos])
            return_positions.append(split_seq_positions[pos])
    return return_sequences, return_positions





def create_sequences_from_targets(sequence_list = [] , positions_list = [],length=8, avoid = []):
    if avoid:
        for avoided_seq in avoid:
            new_sequence_list = []
            new_positions_list = []
            for pos,sequence in enumerate(sequence_list):
                start = positions_list[pos][0]
                seqs, positions = split_sequence(sequence = sequence, split_seq = avoided_seq, length = length)
                new_sequence_list += seqs
                new_positions_list += [(positions[_][0]+start,positions[_][1]+start) for _ in range(len(positions))]
        return new_sequence_list, new_positions_list
</code></pre>

<p>A Sample output:</p>

<pre><code>In [60]: create_sequences_from_targets(sequence_list=['MPHSSLHPSIPCPRGHGAQKA', 'AEELRHIHSRYRGSYWRTVRA', 'KGLAPAEISAVCEKGNFNVA'],positions_list=[(0, 20), (66, 86), (136, 155)],avoid=['SRYRGSYW'],length=3)
Out[60]: 
(['MPHSSLHPSIPCPRGHGAQKA', 'AEELRHIH', 'RTVRA', 'KGLAPAEISAVCEKGNFNVA'],
 [(0, 20), (66, 74), (82, 87), (136, 155)])
</code></pre>

<p>Using regular expressions simplifies the code, but it may or may not be more efficient.</p>

<pre><code>&gt;&gt;&gt; import re
&gt;&gt;&gt; sequence_list = ['MPHSSLHPSIPCPRGHGAQKA', 'AEELRHIHSRYRGSYWRTVRA', 'KGLAPAEISAVCEKGNFNVA'],positions_list=[(0, 20), (66, 86), (136, 155)]
&gt;&gt;&gt; avoid = ['SRYRGSYW']
&gt;&gt;&gt; rex = re.compile("|".join(map(re.escape, avoid)))
</code></pre>

<p>get the positions like this (you'll need to add your offsets to these)</p>

<pre><code>&gt;&gt;&gt; [[j.span() for j in rex.finditer(i)] for i in sequence_list]
[[], [(8, 16)], []]
</code></pre>

<p>get the new strings like this </p>

<pre><code>&gt;&gt;&gt; [rex.split(i) for i in sequence_list]
[['MPHSSLHPSIPCPRGHGAQKA'], ['AEELRHIH', 'RTVRA'], ['KGLAPAEISAVCEKGNFNVA']]
</code></pre>

<p>or the flattened list</p>

<pre><code>&gt;&gt;&gt; [j for i in sequence_list for j in rex.split(i)]
['MPHSSLHPSIPCPRGHGAQKA', 'AEELRHIH', 'RTVRA', 'KGLAPAEISAVCEKGNFNVA']
</code></pre>

python string split