Python exercise: last letter / first letter
<p>I'm a newbie Python student and I'm going through some simple (but now, for me, complicated) exercises. I tried in many ways, but I decided to stop guessing, because I believe it won't be a sane routine of learning.</p>

<p>I have to solve the following exercise:</p>

<blockquote>
  <p>Write a <code>lastfirst(lst)</code> function, that, given a list, returns the
  first word in the list that starts with a different character from the
  last character of the previous word. If there isn't such a word,
  return <code>None</code>.</p>
  
  <p>Example:</p>
  
  <p><code>lst = ['sole','elmo','orco','alba','asta']</code> returns <code>'alba'</code></p>
  
  <p><code>lst = ['sky','you','use','ear','right']</code> returns <code>None</code></p>
</blockquote>

<p>I've tried to solve it, and what I had is this:</p>

<pre><code>lst = ['sole','elmo','orco','alba','asta']

def lastfirst(lst):

    cont = 0
    d = 1 
    for a in lst[cont:]: 
        for b in lst[d:]:       
            if a[-1] != b[0]:
                return lst[d]
            else:
                 cont = cont + 1   
                 d = d + 1  

print(lastfirst(lst))
</code></pre>

<p>The problem I detected is:</p>

<p>The program doesn't make a distinction between taking the first letter of the first word and the last letter of the second word, or the last letter of the first word and the first letter of the second word.</p>

<p>PS: Sorry for my English :)</p>

<p>You would use a double <code>for</code> loop when you need to test every word in <code>lst</code> against every other word in <code>lst</code>, but that's not what we want here. We just need a single <code>for</code> loop, and we need to store the previous word so we can test it against the current word. Like this:</p>

<pre><code>def lastfirst(lst):
    if not lst:
        return None
    prev = lst[0]
    for word in lst[1:]:
        if word[0] != prev[-1]:
            return word
        prev = word
    return None


data = [
    ['sole', 'elmo', 'orco', 'alba', 'asta'], 
    ['sky', 'you', 'use', 'ear', 'right'],
    [],
    ['help', 'please', 'everybody', 'thanks'],
]

for lst in data:
    print(lastfirst(lst))
</code></pre>

<p><strong>output</strong></p>

<pre><code>alba
None
None
thanks
</code></pre>

<p>My function first does</p>

<pre><code>if not lst:
    return None
</code></pre>

<p>so we return immediately if we get passed an empty list. Otherwise, the program will crash when it attempts to do <code>prev = lst[0]</code></p>

<hr>

<p>Here's an efficient way to do the test using a single line. </p>

<pre><code>def lastfirst(lst):
    return next((v for u, v in zip(lst, lst[1:]) if u[-1] != v[0]), None)
</code></pre>

<p>This code is obviously more compact than my previous version, and it <em>might</em> be a little faster. But it <em>is</em> harder to understand, especially if you are new to Python. Some people think that "one-liners" like this are more Pythonic, but actually it is more Pythonic to make your code as readable as possible. :)</p>

python list function for-loop