0

To illustrate my problem, imagine I have a list and I want to compare each element with the next one to check if they are the same value. The problem is that when I try to access the last element of the list and compare it with "the next one", that one is out of range, so I would get an error. So, to avoid this, I put a condition when accessing that last element, so I avoid the comparison.

list = [1, 2, 1, 1, 5, 6, 1,1]

for i in range(len(list)):
    if i == len(list)-1:
        print('Last element. Avoid comparison')
    else:
        if list[i] == list[i+1]:
            print('Repeated')

I guess that there should be a more efficient way to do this. For instance, I was trying to set the condition in the definition of the for loop, something like this:

for i in range(len(list)) and i < len(list)-1

But that is invalid. Any suggestion about how to do this in a more efficient/elegant way?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
nekovolta
  • 496
  • 2
  • 14
  • 1
    I image `for i in range(len(list) - 1)` would solve the problem of trying to access beyond the last element. Then the conditional would become `if list[i] == list[i-1]` – Simon Crowe Dec 27 '21 at 15:57
  • @SimonCrowe the condition should be the same, isn't it? – nekovolta Dec 27 '21 at 16:04
  • Ah, yes I think `[i+1]` should be fine now. With `[i-1]` Python would compare the first and last element on the first iteration because of how the subscript `[-1]` works in Python. I _think_ this would still give the desired result, but not be very readable. – Simon Crowe Dec 27 '21 at 16:10
  • Why not to make it simpler: `all(x == a[0] for x in a)`, this will compare each element with first element in the list and return `True` or `False`. Or `all(a[i] == a[0] for i in range(len(a)))` if you want to deal with indices. – andnik Dec 27 '21 at 16:22
  • @adnik I think the question is looking to compare contiguous pairs of values rather than all values in the list. – Simon Crowe Dec 27 '21 at 17:05
  • Yes, that is, just contiguous pairs. The solution was easy, actually, I tried but I thought I was wrong because `for i in range(len(list) - 1)` the last value of i is `i = len(list) - 2` and I was confused with this. Thank you – nekovolta Dec 27 '21 at 18:15
  • @SimonCrowe, oh, so comparing pairs of neighbouring items. Then, `[a[i] == a[i + 1] for i in range(len(a) - 1)]` would give you list of boolean values: True if items repeat and False otherwise. FYI, DON'T call your variable by KEY WORD, namely `list`. – andnik Dec 27 '21 at 19:32
  • Does this answer your question? [Iterate through pairs of items in a Python list](https://stackoverflow.com/questions/5764782/iterate-through-pairs-of-items-in-a-python-list) – Tomerikoo Dec 28 '21 at 16:30

9 Answers9

1

You can utilize the functionality of range as follows:

for i in range(1, len(list)):
    if list[i-1] == list[i]:
        print('Repeated')

In this way, you won't overrun the list.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
itprorh66
  • 3,110
  • 4
  • 9
  • 21
  • I need to start `i` in 0, as I need to do other operations with the index in 0. Starting in 1 solve the problem, but not for my purpose – nekovolta Dec 27 '21 at 16:00
  • If you need to do certain operations with the 0 index, do them outside the loop by directly dealing with list[0]!! – itprorh66 Dec 27 '21 at 16:04
1

If you need to start from 0, you should use:

for i in range(len(list) - 1):
    if list[i] == list[i + 1]:
        print('Repeated')

The parameter stop of range function is just integer, so you can use value len(list) - 1 instead of len(list) to stop iterating on last but one element.

Oleksii Tambovtsev
  • 2,666
  • 1
  • 3
  • 21
1

Other answers have solved this, but I think it's worth mentioning an approach that may be closer to idiomatic Python. Python provides iterable unpacking and other tools like the zip function to avoid accessing elements of sequences by index.

# Better to avoid shadowing the build-in name `list`
a_list = [1, 2, 1, 1, 5, 6, 1, 1]

for value, following_value in zip(a_list, a_list[1:]):
    if value == following_value:
       print("Repeated!")

The more-itertools package also has a useful function for this called pairwise.

Simon Crowe
  • 301
  • 3
  • 14
0

start from one and look backwards

for i in range(1, len(list)): 
    if list[i-1] == list[i]:
        print('Repeated')
jeana
  • 11
  • 2
  • I need to start i in 0, as I need to do other operations with the index in 0. Starting in 1 solve the problem, but not for my purpose – nekovolta Dec 27 '21 at 16:01
0

This works!

list = [1, 2, 1, 1, 5, 6, 1, 1]

for i in range(len(list)):    
    if i+1 < len(list) and list[i] == list[i+1]:
        print('Repeated')
giannkas
  • 178
  • 3
  • 14
0
  • len(list) is 8
  • range(len(list)) is 0, 1, ..., 7 but you want the for loop to skip when the index is 6 right?

so given that case ... if i == len(list)-1: this condition will be True when the index is 7 (not the index that you want)

Just change that to if i == len(list)-2:

Reddy Tintaya
  • 141
  • 2
  • 8
0

There are many ways to do this. The most common one is to use zip to pair each item with its successor:

if any(item == successor for item,successor in zip(lst,lst[1:])):
    print('repeated')

groupby from itertools is also a popular choice (but not optimal for this):

if any(duplicate for _,(_,*duplicate) in itertools.groupby(lst)):
    print('repeated')

A for-loop would only need to track the previous value (no need for indexing):

prev = object() # non-matching initial value
for x in lst:
    if prev==x:              # compare to previous
       print('repeated')
       break
    prev = x                 # track previous for next iteration

Iterators can be interesting when traversing data in parallel (here the elements and their predecessors):

predecessor = iter(lst)         # iterate over items from first
for x in lst[1:]:               # iterate from 2nd item
    if x == next(predecessor):  # compare to corresponding predecessor
        print('repeated')
        break
Alain T.
  • 40,517
  • 4
  • 31
  • 51
0
list = [1, 2, 1, 1, 5, 6, 1,1]

for i in range(len(list)):
    if list[i] in list[i+1:i+2]:
        print('repeated')
whitespace
  • 789
  • 6
  • 13
0

If you use only numbers in your list, you might want to work with numpy for instance:

import numpy as np
np_arr = np.array(lst)  # don't use 'list' for your object name. 
diffs = np.diff(np_arr)
diffs_indices = np.where(diffs != 0)[0]

It is unclear what your exact uses, but for example in my code, you will get:

>>> diffs_indexes
array([0, 1, 3, 4, 5])

Which are the indices where elelment[i] != element[i+1]

Shaq
  • 303
  • 1
  • 10