Remove an even/odd number from an odd/even Python list
<p>I am trying to better understand list comprehension in Python.  I completed an online challenge on codewars with a rather inelegant solution, given below.</p>

<p>The challenge was:</p>

<ol>
<li>Given a list of even numbers and one odd, return the odd</li>
<li>Given a list of odd numbers and one even, return the even</li>
</ol>

<p>My (inelegant) solution to this was:</p>

<pre><code>def find_outlier(integers):
    o = []
    e = []
    for i in integers:
        if i % 2 == 0:
            e.append(i)
        else:
            o.append(i)
    # use sums to return int type
    if len(o) == 1:
        return sum(o)
    else:
        return sum(e)
</code></pre>

<p>Which works fine, but seems to be pretty brute force.  Am I wrong in thinking that starting (most) functions with placeholder lists like <code>o</code> and <code>e</code> is pretty "noob-like"?</p>

<p>I would love to better understand why this solution works for the odd list, but fails on the even list, in an effort to better understand list comprehension:</p>

<pre><code>def find_outlier(integers):
    if [x for x in integers if x % 2 == 0]:
       return [x for x in integers if x % 2 == 0]
    elif [x for x in integers if x % 2 != 0]:
       return [x for x in integers if x % 2 != 0]
    else:
        print "wtf!"

o = [1,3,4,5]
e = [2,4,6,7]

In[1]: find_outlier(o)
Out[1]: [4]

In[2]: find_outlier(e)
Out[2]: [2, 4, 6]
</code></pre>

<p>Where <code>Out[2]</code> should be returning <code>7</code>.</p>

<p>Thanks in advance for any insights.</p>

<p>Your attempt fails because the first <code>if</code> is <em>always going to be true</em>. You'll always have a list with at least 1 element; either the odd one out is odd and you tested a list with all even numbers, otherwise you have a list with the <em>one</em> even number in it. Only an <em>empty</em> list would be false.</p>

<p>List comprehensions are not the best solution here, no. Try to solve it instead with the minimum number of elements checked (the first 2 elements, if they differ in type get a 3rd to break the tie, otherwise iterate until you find the one that doesn't fit in the tail):</p>

<pre><code>def find_outlier(iterable):
    it = iter(iterable)
    first = next(it)
    second = next(it)
    parity = first % 2
    if second % 2 != parity:
        # odd one out is first or second, 3rd will tell which
        return first if next(it) % 2 != parity else second
    else:
        # the odd one out is later on; iterate until we find the exception
        return next(i for i in it if i % 2 != parity)
</code></pre>

<p>The above will throw a <code>StopIteration</code> exception if there are either fewer than 3 elements in the input iterable, or there is no exception to be found. It also won't handle the case where there is more than one exception (e.g. 2 even followed by 2 odd; the first odd value would be returned in that case).</p>

python list list-comprehension