Reputation: 1960
l = [2,4,6,12,14,16,21,27,29,31]
I want to split it to lists, such that each list's elements are a monotonic list with diff of 2 between elements:
new_l = [[2,4,6], [12,14,16],[21], [27,29,31]]
What is the most efficient way to do this?
Upvotes: 1
Views: 152
Reputation: 628
Update
It is possible to avoid Python loops altogether and only use comprehensions
(along with zip
) for some efficiency gain. You can do that like the following:
l = [2,4,6,12,14,16,21,27,29,31, 44]
n = len(l)
#Find the splitting points (where the monotonic condition breaks):
splitting_points = [0] + [k for k in range(1, n) if l[k] - l[k - 1] != 2]
if splitting_points[-1] != n:
splitting_points.append(n)
#Then split the list into intervals having bounds in the splitting_points:
new_l = [l[i: j] for i, j in zip(splitting_points[:-1], splitting_points[1:])]
print(new_l)
This "should" be quite faster than loops (especially for large lists), but I haven't done any benchmarking.
Original
You have to iterate over the initial list l
, maintain a current list that has the current monotonic sequence, and whenever the new iterated element breaks the monotonic condition, insert the current list and clear it.
Here's a code that does exactly that:
l = [2,4,6,12,14,16,21,27,29,31]
new_l = []
current_l = [l[0]] #initially, insert the first element
for k in range(1, len(l)):
if l[k] - current_l[-1] == 2: #if the monotonic condition is satisfied
current_l.append(l[k]) #we append the element
else:
new_l.append(current_l) #otherwise, we append the previous list to the answer
current_l = [l[k]] #and clear the running sequence
new_l.append(current_l) #there will always be a last sequence not appended to the answer
print(new_l)
Upvotes: 1
Reputation: 5949
You could identify indices where to split and then apply np.split
like so:
np.split(l, np.flatnonzero(np.diff(l)!=2) + 1)
Output:
[array([2, 4, 6]), array([12, 14, 16]), array([21]), array([27, 29, 31])]
However, playing with arrays of different lenghts is never efficient so that's why np.split
is quite slow.
Upvotes: 1