AbSaintDane
AbSaintDane

Reputation: 77

Looping with Consecutive Elements

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

Answers (5)

AMACB
AMACB

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

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

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

Shan Valleru
Shan Valleru

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

ShadowRanger
ShadowRanger

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 ziping, just less efficiently (generating index integers and explicitly indexing is surprisingly expensive in Python relative to native iteration).

Upvotes: 2

Knells
Knells

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

Related Questions