Reputation: 1747
Given a list of numbers, how can I split it whenever the distance of two adjacent elements is larger than n?
Input:
n = 3
l = [1, 2, 5, 3, -2, -1, 4, 5, 2, 4, 8]
Output:
[[1, 2, 5, 3], [-2, -1], [4, 5, 2, 4], [8]]
Upvotes: 2
Views: 1717
Reputation: 679
n = 3
a = [1, 2, 5, 3, -2, -1, 4, 5, 2, 4, 8]
b = [abs(i - j) > n for i, j in zip(a[:-1], a[1:])]
m = [i + 1 for i, j in enumerate(b) if j is True]
m = [0] + m + [len(a)]
result = [a[i: j] for i, j in zip(m[:-1], m[1:])]
print(result)
Upvotes: 1
Reputation: 1325
Here's a more primitive piece of code that achieves what you want to do, even though it is not efficient (see Reut Sharabani's answer for a more efficient solution.)
# Input list
l = [1, 6, 5, 3, 5, 0, -3, -5, 2]
# Difference to split list with
n = 3
output = []
t = []
for i in range(1, len(l)):
t.append(l[i])
if abs(l[i] - l[i - 1]) < n:
None
else:
output.append(t)
t = []
return output
Upvotes: 1
Reputation: 31339
You can do it using zip:
# initialization
>>> lst = [1, 2, 5, 3, -2, -1, 4, 5, 2, 4, 8]
>>> n = 3
Find splitting locations using zip:
>>> indices = [i + 1 for (x, y, i) in zip(lst, lst[1:], range(len(lst))) if n < abs(x - y)]
Slice subslists using previous result:
# pad start index list with 0 and end index list with length of original list
>>> result = [lst[start:end] for start, end in zip([0] + indices, indices + [len(lst)])]
>>> result
[[1, 2, 5, 3], [-2, -1], [4, 5, 2, 4], [8]]
Upvotes: 7
Reputation: 1747
Code
from boltons import iterutils
def grouponpairs(l, f):
groups = []
g = []
pairs = iterutils.pairwise(l + [None])
for a, b in pairs:
g.append(a)
if b is None:
continue
if not f(a, b):
groups.append(g)
g = []
groups.append(g)
return groups
Test
grouponpairs([1, 2, 5, 3, -2, -1, 4, 5, 2, 4, 8], lambda a, b: abs(a - b) <= 3)
# [[1, 2, 5, 3], [-2, -1], [4, 5, 2, 4], [8]]
Upvotes: 1