Reputation: 9
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.
I have to solve the following exercise:
Write a
lastfirst(lst)
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, returnNone
.Example:
lst = ['sole','elmo','orco','alba','asta']
returns'alba'
lst = ['sky','you','use','ear','right']
returnsNone
I've tried to solve it, and what I had is this:
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))
The problem I detected is:
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.
PS: Sorry for my English :)
Upvotes: 1
Views: 2504
Reputation: 55479
You would use a double for
loop when you need to test every word in lst
against every other word in lst
, but that's not what we want here. We just need a single for
loop, and we need to store the previous word so we can test it against the current word. Like this:
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))
output
alba
None
None
thanks
My function first does
if not lst:
return None
so we return immediately if we get passed an empty list. Otherwise, the program will crash when it attempts to do prev = lst[0]
Here's an efficient way to do the test using a single line.
def lastfirst(lst):
return next((v for u, v in zip(lst, lst[1:]) if u[-1] != v[0]), None)
This code is obviously more compact than my previous version, and it might be a little faster. But it is 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. :)
Upvotes: 1
Reputation: 1485
I think it will work (in python 3):
lst = ['sole','elmo','orco','alba','asta']
def lastfirst(lst):
for i in range(len(lst)-1):
if lst[i][-1] != lst[i+1][0] :
return lst[i+1]
return None
print(lastfirst(lst))
Output:
alba
Explanation(Modifications needed in your code) :
- We don't need two for loops we can do it in single for loop.
- Although you do increment
cont
variable inelse
statement but it will always compare it with same string which isa
.
Another Input :
lst = ['sky','you','use','ear','right']
Output:
None
Hope it will help you.
Upvotes: 2
Reputation: 12026
Here's a solution using itertools.
First, define a function that returns a boolean if your condition is met:
def check_letters(apair):
"In a pair, check last letter of first entry with first letter of second"
return apair[0][-1] == apair[1][0]
Now we use the pairwise function from the itertools
module recipes:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
And finally:
lst = ['sole','elmo','orco','alba','asta']
lstlast = [item[1] for item in pairwise(lst) if not check_letters(item)]
# returns ['alba']
Upvotes: 0