How to split a list into sublists with specific range for each sublist?

Question:

I want to split a list into sublist with specific ‘if statement’ for each sublist.
For examle:
input:

a = [1, 2, 7.9, 3, 4, 3.7, 5, 6, 2.2, 7, 8, 1.2, 5.7]

output:

b = [[1, 1.2, 2], [2.2, 3, 3.7, 4], [5, 5.7, 6], [7, 7.9, 8]]

Values should be grouped by certain range. here it is between (1:2); (2.1:4); (4.1:6); (6.1:8). I hope I was able to get my point across.

Asked By: Salkynbekov

||

Answers:

You seem to want to divide your data into buckets of width dx. Assuming this, your expected output would be:

[[1, 1.2, 2], [2.2, 3], [3.7, 4], [5, 5.7, 6], [7, 7.9, 8]]

First, let’s sort the input numbers:

numbers = sorted(a)

Now, we’ll iterate over this sorted list, and append to a bucket list as long as appending the current number wouldn’t exceed our desired range for this bucket. If appending the current number would cause the desired range to be exceeded, then we create a new bucket and start appending to it:

bucket = []
result = [bucket]
for n in numbers:
    # bucket is empty, or bucket range <= dx, so append
    if not bucket or n - bucket[0] <= dx: 
        bucket.append(n)
    else:
        bucket = [n] # Create a new bucket with the current number
        result.append(bucket) # Add it to our result array

This gives your expected result:

result = [[1, 1.2, 2], [2.2, 3], [3.7, 4], [5, 5.7, 6], [7, 7.9, 8]]
Answered By: Pranav Hosangadi

The logic is not fully clear. Assuming you want to group by bins of width 2 (1-2, 3-4, 5-6, …) with the right boundary included.

We can use a dictionary to temporarily hold the bins and to facilitate the creation of the sublists.

from math import ceil

a = [1, 2, 7.9, 3, 4, 3.7, 5, 6, 2.2, 7, 8, 1.2, 5.7]
dx = 2

d = {}

for x in sorted(a):
    k = ceil(x+1)//dx
    d.setdefault(k, []).append(x)

b = list(d.values())

Output:

[[1, 1.2, 2], [2.2, 3, 3.7, 4], [5, 5.7, 6], [7, 7.9, 8]]
Answered By: mozway
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.