list of strings - remove commonalities of common strings
<p>I'm struggling to come up with a way to solve this problem (and how to come up with a name for this question on stackoverflow).</p>

<p>I need to somehow remove commonalities of strings preserving the remainder.  </p>

<p>Given a list such as the following:</p>

<pre><code>l = ('first',
     'first.second',
     'first.second.third',
     'a.b.c',
     'x.y.z',
     'x.y') 
</code></pre>

<p>I'm hoping to have a list output as:</p>

<pre><code>('first',
 'second',
 'third', 
 'a.b.c',
 'x.y',
 'z' ) 
</code></pre>

<p>as you can see, when <code>first.second</code> subtracts <code>first</code> and remains <code>second</code>. <code>first.second</code> is subtracted from <code>first.second.third</code> we get <code>third</code>.  <code>a.b.c</code> doesn't have anything to subtract from itself, so it remains.  <code>x.y</code> is subtracted from <code>x.y.z</code> and <code>z</code> remains.</p>

<p>I'm thinking maybe a <code>sort(key=len)</code> will be part of the solution, as well as some sort of recursion to end up with the string remainder.  I'm hoping for a clean way to remove commonalities of each string in the list. </p>

<p>I believe you need to define your problem a little more exactly before writing a solution. Here's what I infer from your test case:</p>

<ol>
<li>"Members" are delimited by periods: the same "member" can't appear in two tuple items.</li>
<li>Each member should only appear once.</li>
</ol>

<p>The problem, though, is that the <em>precedence</em> is ambiguous. For example, in the following sequence:</p>

<pre><code>lst = ('a.b.c',
       'a.b.d')
</code></pre>

<p>Where do 'a' and 'b' belong? Your test case implies that a common member should go to the one with the least common members (so "z" doesn't stay with "x.y.z"), but there are plenty of edge cases that need to be considered. You will need to put your requirements in a more exact format.</p>

<p>Adopting the much simpler rule that a "member" should stay in the first place that it appears, the following function does the trick:</p>

<pre><code>def remove_common(lst):
    seen = set()
    res = []
    for i in lst:
        members = i.split('.')
        res.append('.'.join(w for w in members if w not in seen))
        seen |= set(members)
    return tuple(res)
</code></pre>

<p>This gives a result very close to yours:</p>

<pre><code>&gt;&gt;&gt; remove_common(l)
('first', 'second', 'third', 'a.b.c', 'x.y.z', '')
</code></pre>

python algorithm