AennaPhD
AennaPhD

Reputation: 147

Find the first element in a list where all subsequent values increment by one

I would like to find the value in a list, after which all other values increase by 1 only.

# Input
my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
my_list2 = [6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28]
my_list3 = [5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25]
# Output
my_list1 = 15
my_list2 = 20
my_list3 = 18

I was thinking about looping backwards through the lists and when the decrease is larger than 1, extract the value at this position.

for x in reversed(my_list1):
    if x decrease > 1:
        print(x)

Upvotes: 1

Views: 1555

Answers (8)

yatu
yatu

Reputation: 88276

Here's an itertools based one, useful if we have a very long list, so we don't have load it into memory. Here dropwhile will drop values from the iterable while the condition holds, we only need to take the next element in the resulting iterable. Note that next has a default argument, which we can just set to None to avoid having the StopIteration error being raised:

from itertools import tee, dropwhile

def first_diff(it):
    i, j = tee(reversed(it), 2)
    next(j)
    return next((dropwhile(lambda e: e==(next(j)+1), i)), None)

first_diff(my_list1)
# 15
first_diff(my_list2)
# 20
first_diff(my_list3)
# 18

Upvotes: 5

Georgy
Georgy

Reputation: 13727

Similar to the Splitting list based on missing numbers in a sequence, you can use itertools.groupby to group consecutive runs of numbers, and from there to get the first value of the last run:

from itertools import groupby

my_list = [2, 5, 7,8,9,10,11,12,13, 15,16,17,18,19,20,21,22,23,24]
first_value = None
for _, group in groupby(enumerate(my_list), lambda x: x[1] - x[0]):
    first_value = next(group)[1]
print(first_value)
# 15

Upvotes: 0

RoadRunner
RoadRunner

Reputation: 26315

You could zip() the reversed() lists into pairs, then use next() to get the first pair where the difference is greater than 1. We can then unpack the first item from the result.

def first_diff_pair(lst):
    return next(
        (fst for fst, snd in zip(reversed(lst), reversed(lst[:-1])) if fst - snd > 1),
        None,
    )

To avoid next() returning StopIteration when no result is found and the iterator is exhausted, we can set the default value to None.

Output:

>>> first_diff_pair([2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])
15
>>> first_diff_pair([6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28])
20
>>> first_diff_pair([5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25])
18

Upvotes: 2

GZ0
GZ0

Reputation: 4273

Here is a basic loop-based implementation.

def get_first_diff(my_list):
    reversed_iter = reversed(my_list)
    last = next(reversed_iter)
    for v in reversed_iter:
        if last - v != 1:
           return last
        last = v
    return None

Upvotes: 1

VPfB
VPfB

Reputation: 17332

Here is my attempt:

my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

tmplist = [x - i for i, x in enumerate(my_list1)]
first = my_list1[tmplist.index(tmplist[-1])]
# result 15

How it works:

# tmplist is [2, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6]

Repeating numbers show places of increasing sequences (by +1) in the original list. Last item (tmplist[-1]) is 6, we want to get the position of the first such item (tmplist.index(...)), because there the sequence starts. Finally we look up the value at that index (my_list1[...])

Upvotes: 0

Mobina
Mobina

Reputation: 7109

This is a solution with no duplicate code:

my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
my_list2 = [6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28]
my_list3 = [5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25]

def getIncreaseStartPoint(nums):
  i = len(nums) - 1
  while (nums[i] - nums[i - 1] == 1):
    i -= 1
    if (i == 0):
      return nums[0]
  return nums[i]

print("mylist_1 =", getIncreaseStartPoint(my_list1))
print("mylist_2 =", getIncreaseStartPoint(my_list2))
print("mylist_3 =", getIncreaseStartPoint(my_list3))

Upvotes: 0

Suryansu Dash
Suryansu Dash

Reputation: 95

Well, I tried this, and it worked, but there maybe better and more efficient solutions to it too,

l = len(my_list1) - 1
for x in reversed(my_list1):
    if my_list1[l] - my_list1[l - 1] == 1:
      l -= 1
      continue
    else:
      print(x)
      break

Upvotes: 1

Ronald
Ronald

Reputation: 3315

There are several possibilities with list comprehensions. Here I collect every number that increased by more then one, store them in a list and show the last one:

print([my_list1[i+1] for i in range(len(my_list1)-1) if my_list1[i+1] - my_list1[i] > 1][-1])
print([my_list2[i+1] for i in range(len(my_list2)-1) if my_list2[i+1] - my_list2[i] > 1][-1])
print([my_list3[i+1] for i in range(len(my_list3)-1) if my_list3[i+1] - my_list3[i] > 1][-1])

Upvotes: 1

Related Questions