'Python find indices of subarrays which are continuous and increasing with difference of 1

The input is always strictly increasing. I could write this with a for loop and lots of if-else conditions, but is there some simple way? Here is an example:

input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]

input: [1,2,3,4]
output: [[0,1,2,3]]

input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]

For example here is the code I wrote

def get_mergable_indices(sent_order):
    mergable_indices = []
    continuous_sents = [0]
    for index, value in enumerate(sent_order):
        if index == 0:
            continue
        else:
            if value - sent_order[index-1] == 1:
                continuous_sents.append(index)
            else:
                if len(continuous_sents)>1:
                    mergable_indices.append(continuous_sents)
                continuous_sents = [index]
    if len(continuous_sents)>1:
        mergable_indices.append(continuous_sents)
    return mergable_indices

It's too big want to reduce it



Solution 1:[1]

Maybe you can try this:

def get_mergable_indices(sent_order):
    lst, res = [j-i for i, j in enumerate(sent_order)], []
    ci = 0
    for i in set(lst):
        lci = lst.count(i)
        if lci  > 1:
            res.append(list(range(ci, lci + ci)))
        ci += lci 
    return res

output:

>>> get_mergable_indices([2,3,4,6,8,9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices([1,2,3,4])
[[0, 1, 2, 3]]
>>> get_mergable_indices([0,1,2,4,6,7,8,10,12,13,14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]

Solution 2:[2]

This can easily be done without using any module.

def get_mergable_indices(sent_order):
    lst = sent_order
    out = []

    l = []
    for a in range(max(lst)):  # set range to the max number in the list.
        try:
            if lst[a]+1 == lst[a+1]:  # check current number plus 1 is equal to next number
                l.append(a)
                l.append(a+1)
            else: # if not equal then append l to the out list also set the l to an empty list.
                if l:
                    out.append(list(set(l)))
                    l = []
        except IndexError:
            pass
    out.append(list(set(l))) 
    return (out)

output

input: [2,3,4,6,8,9]
output: [[0,1,2],[4,5]]

input: [1,2,3,4]
output: [[0,1,2,3]]

input: [0,1,2,4,6,7,8,10,12,13,14]
output: [[0,1,2], [4,5,6], [8,9,10]]

Solution 3:[3]

This can accept any iterable sequence:

from itertools import pairwise

def get_mergable_indices(sent_order):
    result = []
    curr = []
    for idx, (i, j) in enumerate(pairwise(sent_order)):
        if j - i == 1:
            curr.append(idx)
        elif curr:
            curr.append(idx)
            result.append(curr)
            curr = []

    if curr:
        curr.append(idx + 1)
        result.append(curr)

    return result

Output:

>>> get_mergable_indices([2, 3, 4, 6, 8, 9])
[[0, 1, 2], [4, 5]]
>>> get_mergable_indices(range(1, 5))
[[0, 1, 2, 3]]
>>> get_mergable_indices([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])
[[0, 1, 2], [4, 5, 6], [8, 9, 10]]

Solution 4:[4]

This is my approach:

def check_continuous(inp_list):
    idx = idy = 0
    res = [[]]
    while idx < len(inp_list) - 1:
        # Not append repeated indices
        if inp_list[idx] - inp_list[idx+1] == -1: # If the next element is 1 higher, just check for -1
            if idx not in res[idy]:
                res[idy].append(idx)
            if idx+1 not in res[idy]:
                res[idy].append(idx+1)
        else:
            # Don't append empty lists
            if res[idy]:
                res.append([])
                idy += 1
        idx += 1
    return res

print(check_continuous([2,3,4,6,8,9]))
# [[0, 1, 2], [4, 5]]
print(check_continuous([1,2,3,4]))
# [[0, 1, 2, 3]]
print(check_continuous([0,1,2,4,6,7,8,10,12,13,14]))
# [[0, 1, 2], [4, 5, 6], [8, 9, 10]]

I think this could be highly improved

Solution 5:[5]

As I have mentioned in the comments, np.diff can be a good choice in this regard. The accepted answer used two loops again, but is written in smaller form, and is not so different than other answers. The problem can be solved by Just NumPy as:

a = np.array([0, 1, 2, 4, 6, 7, 8, 10, 12, 13, 14])

diff = np.diff(a, prepend=a[0]-2)                                      # [2 1 1 2 2 1 1 2 2 1 1]
diff_w = np.where(diff == 1)[0]                                        # [ 1  2  5  6  9 10]

mask_ = np.diff(diff_w, prepend=diff_w[0]-2)                           # [2 1 3 1 3 1]
mask_ = mask_ != 1                                                     # [ True False  True False  True False]

con_values = np.insert(diff_w, np.where(mask_)[0], diff_w[mask_] - 1)  # [ 0  1  2  4  5  6  8  9 10]

# result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 1) != 1)[0])
result = np.split(con_values, np.where(np.diff(con_values, prepend=con_values[0] - 2) != 1)[0])[1:]
# [array([0, 1, 2], dtype=int64), array([4, 5, 6], dtype=int64), array([ 8,  9, 10], dtype=int64)]

I have tested this code on your examples and some others and it works. But, if there be any problem using other samples, it can be handled with some little changes by inspiration from this code. I wrote this code in separate parts to be understandable more. You can combine them in just one line if it is important for you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rainibooo
Solution 2
Solution 3
Solution 4
Solution 5 Ali_Sh