Sheikh Rahman
Sheikh Rahman

Reputation: 915

Find consecutive integers in a list

I am trying to find consecutive values from an unsorted list. Experimental code below:

num = [8, 9, 4, 1, 2, 3]

#(num[0+1])  next value

for i in range(len(num)-1):  # not using -1 will cause index error
    if num[i]+1==num[i+1]:
        print('Con',num[i])

Problem: I am unable to get the last value with this current code. My output excludes the last value. Here is what I get (no 9 or no 3):

Con 8
Con 1
Con 2

I have seen a few complex solutions which were a little difficult for me to understand. Is it possible to tweak the for loop part a little and get the entire sequence? Thanks a lot.

Upvotes: 6

Views: 5432

Answers (5)

Mykola Zotko
Mykola Zotko

Reputation: 17794

You can use the function groupby:

from itertools import groupby

num = [8, 9, 4, 1, 2, 3]

# Enumerate and get differences between counter—integer pairs
# Group by differences (consecutive integers have equal differences)  
gb = groupby(enumerate(num), key=lambda x: x[0] - x[1])

# Repack elements from each group into list
all_groups = ([i[1] for i in g] for _, g in gb)

# Filter out one element lists
list(filter(lambda x: len(x) > 1, all_groups))
# [[8, 9], [1, 2, 3]]

Upvotes: 5

siggi_pop
siggi_pop

Reputation: 627

num = [8, 9, 4, 1, 2, 3]

def con(rng, pos=0):
    if pos < len(rng):
        if (pos > 0 and rng[pos]-1 == rng[pos-1]) or (pos < len(rng) -1 and rng[pos]+1 == rng[pos+1]):
            print("con", rng[pos])
        con(rng, pos+1)

con(num)

edit: this is solution is based on concurrent function, and needs only the list as argument. As long as they are within lower-/upperbound of list, the function will check if (previous number)-1 or (next number)+1 are equal (this number) output will be: con 8 con 9 con 1 con 2 con 3

Upvotes: 0

Siavas
Siavas

Reputation: 5090

One way would be to print both numbers when you found them to be consecutive, but also check that the one at index i-1 was not in the consecutive list as well so that the number at index i is not printed twice:

num = [8, 9, 4, 1, 2, 3]

for i in range(len(num)-1):  # not using -1 will cause index error
    if num[i] + 1 == num[i + 1]:
        if i == 0 or (i - 1 >= 0 and num[i - 1] != num[i] - 1):
            print('Con', num[i])
        print('Con', num[i + 1])

Could try with a more complex list as well:

num = [8, 9, 4, 1, 2, 3, 4, 4, 8, 9, 1, 2, 3, 0, 1, 5, 6, 1]

for i in range(len(num)-1):  # not using -1 will cause index error
    if num[i] + 1 == num[i + 1]:
        if i == 0 or (i - 1 >= 0 and num[i - 1] != num[i] - 1):
            print('Con', num[i])
        print('Con', num[i + 1])

Upvotes: 0

Levi Lesches
Levi Lesches

Reputation: 1601

This is because you only check the next number. When you want the second number (like 9 or 3), you have to include a check for the previous number too. This will make the if a bit longer, but it'll work.

num=[8,9,4,1,2,3]

for i in range(len(num)):
    if (
        (  # check for the next number
            i + 1 != len (num) and  # don't check the end of the list
            num[i]+1==num[i+1] 
        ) or (  # check for the previous number
            i != 0 and  # don't check before the list
            num [i-1] == num [i] - 1
        )
    ): print('Con',num[i])

Also, I had to remove the -1 in your range, because I already do a manual check, and as pointed out, this prvented 3 from being shown.

Upvotes: 1

H4kor
H4kor

Reputation: 1562

Your code only tests in one direction (being followed by a consecutive number). For the full sequence you have to test in both direction.

num=[8,9,4,1,2,3]

assert(len(num) > 1)
for i, n in enumerate(num):
    if i != 0:
        if n == num[i-1] + 1:
            print("Con", n)
            continue
    if i != len(num) - 1:
        if n == num[i+1] - 1:
            print("Con", n)

Upvotes: 1

Related Questions