Reputation: 77
I'm a beginner in Python programming and I'm having some trouble with some list stuff.
So I want to write a function that returns a boolean value. The function will inform the user whether there is a duplicate consecutive pair of elements in the list he or she entered. By the way, I want to do this using only len()
, range()
, loops
, if-statements
, variables and arithmetic (no built in functions).
For example:
contains_consecutive_duplicates([1,3,3]) should return True
contains_consecutive_duplicates([3,2,3]) should return False
My code:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
My logic to this was as follows: Each time the for loop would run, i
would refer to some element in the list. If that element was such that the element before it or after it was equal to it, then the for loop would return true. If not, keep searching. If there are none, it would return false.
Now, I actually understand where the error is (I think). The problem is that I don't know how to solve it. I think the for loop is running into a problem at the beginning (when i
is reffering to the 0th element). There is no element before the 0th element, hence the error:
"index out of range"
P.S: Is that how you return a boolean value?
Is there a better way to do this?
I would appreciate any help given! Thanks in advance!
Upvotes: 0
Views: 997
Reputation: 1298
Try this:
def contains_consecutive_duplicates(xs):
for i in xs:
if xs.indexOf(i)==len(xs):
break
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
else:
return False
What you are doing is trying to do is evaluate xs[i+1]
, but that does not exist.
Upvotes: 1
Reputation: 160407
By using only range
, for
and if
statements, this can be done with:
def contains_consequtive_duplicates(xs):
for i in range(len(xs)-1):
if xs[i] == xs[i+1]: return True
return False
You access lists with their index
and not by their value (which you are by using for i in list
). Additionally, if you perform the check xs[i] == xs[i-1]
this will not yield the result you want since x[-1]
will check the end of the list so [3, 2, 3]
will return True.
As a small demonstration:
if contains_consequtive_duplicates([1,3,3]): print "consecutive"
# Prints Consequtive
if contains_consequtive_duplicates([3, 2, 3]): print "consecutive"
# Prints nothing
Upvotes: 1
Reputation: 3121
This should do:
>>> def contains_consecutive_duplicates(xs):
... for i, v in enumerate(xs[:-1]):
... if v == xs[i+1]:
... return True
... else:
... pass
... return False
>>> l1 = [1,3,3]
>>> l2 = [1,3,2]
>>> l3 = []
>>> l4 = [2]
>>> contains_consecutive_duplicates(l1)
True
>>> contains_consecutive_duplicates(l2)
False
>>> contains_consecutive_duplicates(l3)
False
>>> contains_consecutive_duplicates(l4)
False
>>>
Upvotes: 1
Reputation: 155363
@roeland pointed out the problem with assuming iterating the list
directly would get you indices (if you want index and value, use enumerate
). But in this case you don't actually need the index.
For the simple case (where it's known to be a container you can slice), you can just iterate with zip
over offset slices:
def contains_consecutive_duplicates(xs):
return any(x == y for x, y in zip(xs, xs[1:]))
More general solutions can be made with itertools.groupby
to handle the case where you can't slice, but this is simple and involves no imports.
Use of any
in this case is just a short hand to slurp the generator expression and return True
if any values are truthy. The long equivalent form is:
def contains_consecutive_duplicates(xs):
for x1, x2 in zip(xs, xs[1:]):
if x1 == x2:
return True
return False
Since your teacher apparently thinks built-ins are bad, but len
and range
aren't built-ins (they are), you can do this the dumb way:
def contains_consecutive_duplicates(xs):
for i in range(len(xs) - 1):
if xs[i] == xs[i+1]:
return True
return False
Which does the same work as zip
ing, just less efficiently (generating index integers and explicitly indexing is surprisingly expensive in Python relative to native iteration).
Upvotes: 2
Reputation: 837
This should do the trick:
def contains_consecutive_duplicates(xs):
for i in range(1, len(xs) - 1):
if xs[i] == xs[i-1] or xs[i] == xs[i+1]:
return True
return False
It iterates through all values bar the first and last (created by the range function), returning (which ends the loop) if it finds a duplicate.
If it reaches the end and hasn't found a duplicate one must not exist, so it returns False
.
Upvotes: -1