Remove a string that is a substring of other string in the list WITHOUT changing original order of the list
<p>I have a list.</p>

<pre><code>the_list = ['Donald Trump has', 'Donald Trump has small fingers', 'What is going on?']
</code></pre>

<p>I'd like to remove "Donald Trump has" from <code>the_list</code> because it's a substring of other list element.</p>

<p>Here is an important part. I want to do this without distoring the order of the original list.</p>

<p>The function I have (below)  distorts the order of the original list. Because it sorts the list items by its length first. </p>

<pre><code>def substr_sieve(list_of_strings):  
    dups_removed = list_of_strings[:]
    for i in xrange(len(list_of_strings)):
        list_of_strings.sort(key = lambda s: len(s))
        j=0
        j=i+1
        while j &lt;= len(list_of_strings)-1:
            if list_of_strings[i] in list_of_strings[j]:
                try:
                    dups_removed.remove(list_of_strings[i])
                except:
                    pass
            j+=1
    return dups_removed
</code></pre>

<p>A simple solution.</p>

<p>But first, let's also add '<em>Donald Trump</em>', <em>'Donald'</em> and <em>'Trump'</em> in the end to make it a better test case.</p>

<pre><code>&gt;&gt;&gt; forbidden_text = "\nX08y6\n" # choose a text that will hardly appear in any sensible string
&gt;&gt;&gt; the_list = ['Donald Trump has', 'Donald Trump has small fingers', 'What is going on?',
        'Donald Trump', 'Donald', 'Trump']
&gt;&gt;&gt; new_list = [item for item in the_list if forbidden_text.join(the_list).count(item) == 1]
&gt;&gt;&gt; new_list
['Donald Trump has small fingers', 'What is going on?']
</code></pre>

<p>Logic:</p>

<ol>
<li>Concatenate all list element to form a single string.
<strong><code>forbidden_text.join(the_list)</code>.</strong></li>
<li>Search if an item in the list has occurred only once. If it occurs more than once it is a sub-string.<strong><code>count(item) == 1</code></strong></li>
</ol>

<blockquote>
  <p><a href="https://docs.python.org/2/library/stdtypes.html#str.count" rel="nofollow">str.count(sub[, start[, end]])</a></p>
  
  <p>Return the number of non-overlapping occurrences of substring <code>sub</code> in the range <code>[start, end]</code>. Optional arguments <code>start</code> and <code>end</code> are interpreted as in slice notation.</p>
</blockquote>

<hr>

<p><code>forbidden_text</code> is used instead of <code> "" </code>(blank string), to handle a case like these :</p>

<p><code>>>> the_list = ['DonaldTrump', 'Donald', 'Trump']</code></p>

<hr>

<p>As correctly pointed by Nishant, above code fails for <code>the_list = ['Donald', 'Donald']</code></p>

<p>Using a <code>set(the_list)</code> instead of <code>the_list</code> solves the problem.<br>
<code>>>> new_list = [item for item in the_list if forbidden_text.join(set(the_list)).count(item) == 1]</code></p>

python string list