'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 |
