How can I reverse parts of sentence in python?
<p>I have a sentence, let's say:</p>

<p>The quick brown fox jumps over the lazy dog</p>

<p>I want to create a function that takes 2 arguments, a sentence and a list of things to ignore. And it returns that sentence with the reversed words, however it should ignore the stuff I pass to it in a second argument. This is what I have at the moment:</p>

<pre><code>def main(sentence, ignores):
    return ' '.join(word[::-1] if word not in ignores else word for word in sentence.split())
</code></pre>

<p>But this will only work if I pass a second list like so:</p>

<pre><code>print(main('The quick brown fox jumps over the lazy dog', ['quick', 'lazy']))
</code></pre>

<p>However, I want to pass a list like this:</p>

<pre><code>print(main('The quick brown fox jumps over the lazy dog', ['quick brown', 'lazy dog']))
</code></pre>

<p>expected result:
<code>ehT quick brown xof spmuj revo eht lazy dog</code></p>

<p>So basically the second argument (the list) will have parts of the sentence that should be ignored. Not just single words.</p>

<p>Do I have to use regexp for this? I was trying to avoid it...</p>

<p>I have attempted to solve the issue of overlapping ignore phrases e.g. <code>['brown fox', 'quick brown']</code> raised by @PadraicCunningham.</p>

<p>There's obviously a lot more looping and code feels less pythonic so I'd be interested in feedback on how to improve this.</p>

<pre><code>import re

def _span_combiner(spans):
    """replace overlapping spans with encompasing single span"""
    for i, s in enumerate(spans):
        start = s[0]
        end = s[1]
        for x in spans[i:]:
            if x[0] &lt; end:
                end = x[1]
        yield (start, end) 

def main(sentence, ignores):
    # spans is a start and finish indices for each ignore phrase in order of occurence
    spans = sorted(
            [[m.span() for m in re.finditer(p, sentence)][0] for p in ignores if p in sentence]
    )
    # replace overlapping indices with single set of indices encompasing overlapped range
    spans = [s for s in _span_combiner(spans)]
    # recreate ignore list by slicing sentence with combined spans
    ignores = [sentence[s[0]:s[1]] for s in spans]
    for phrase in ignores:
        reversed_phrase = ' '.join([word[::-1] for word in phrase.split()])
        sentence = sentence.replace(phrase, reversed_phrase)

    return ' '.join(word[::-1] for word in sentence.split())

if __name__ == "__main__":
    print(main('The quick brown fox jumps over the lazy dog', ['quick', 'lazy']))
    print(main('The quick brown fox jumps over the lazy dog', ['brown fox', 'lazy dog']))
    print(main('The quick brown fox jumps over the lazy dog', ['nonexistent' ,'brown fox', 'quick brown']))
    print(main('The quick brown fox jumps over the brown fox', ['brown fox', 'quick brown']))
</code></pre>

<p>results:</p>

<pre><code>ehT quick nworb xof spmuj revo eht lazy god
ehT kciuq brown fox spmuj revo eht lazy dog
ehT quick brown fox spmuj revo eht yzal god
ehT quick brown fox spmuj revo eht brown fox
</code></pre>

python python-3.x