# Group counter for ranges of values

I have this grouping thing, which is would be a switch case if it weren't for the ranges or a Counter of some sorts, but as there are those ranges I don't know how to implement this any more efficiently.

def getGroups(user_array):
# group1 is group 1-10 x
group1 = 0
# group2 is group 10-50 x
group2 = 0
# group3 is group 50-100 x
group3 = 0
# group4 is group 100-200 x
group4 = 0
# group5 is group 200-500 x
group5 = 0
# group6 is group 500 - 1000 x
group6 = 0
# group7 is group 1000+ x
group7 = 0

for user in user_array:
if user.x_count == 0:
pass
elif user.x_count <= 10:
group1 += 1
elif user.x_count <= 50:
group2 += 1
elif user.x_count <= 100:
group3 += 1
elif user.x_count <= 200:
group4 += 1
elif user.x_count <= 500:
group5 += 1
elif user.x_count <= 1000:
group6 += 1
else:
group7 += 1
return [group1, group2, group3, group4, group5, group6, group7]

• For what type of application are you using/planning to use this? – AlexV Apr 7 at 20:39
• @Alex Does it matter? I'm trying to group some users for a small project for visualisation. – creyD Apr 7 at 21:55
• Indeed, it does. Your application can greatly influence what aspects matter most about your code. Random examples: hyper-critical, real-time, background application, code it and never touch again? Aim for fast execution. You/others should be able to "play" with it? Ease of use and clarity are prime considerations here. – AlexV Apr 7 at 22:13
• Also, does user_array only contain int values, or can it contain floating point numbers? – AJNeufeld Apr 8 at 1:57
• @Alex Ah ok, the focus is mainly performance as we use it to group the results of some mined data... And yes it only contains int values. – creyD Apr 8 at 8:28

If your data is strictly integer values, you can use user.x_count in range(...) to test whether or not the user.x_count value is a member of the range(...) set. Ie)

def getUsers(user_array):
group1 = sum(1 for user in user_array if user.x_count in range(1, 11))
group2 = sum(1 for user in user_array if user.x_count in range(11, 51))
# ... etc ...


This unfortunately will require several passes through your user_array data, so will not work if that data is ephemeral, such as iterator or generator based.

A more complex method will categorize the user.x_count value into a group value, and then increment the appropriate group counter. bisect will find an insertion index in a sorted array, so we can leverage this to turn a user.x_count into a group based on its corresponding insertion index. This will function properly if floating point values are encountered.

import bisect

def getUsers(user_array):
thresholds = (0, 10, 50, 100, 200, 500, 1000)
groups = [0] * (len(thresholds) + 1)

for user in user_array:
groups[bisect.bisect_left(thresholds, user.x_count)] += 1

return groups[1:]


Notice there are no more group-specific variables, like group1. Instead, all counters are created based on data, allowing you to add additional groups without modifying lines of code; you just modify data.

• That second solution looks really good. We don't need the temporary variables anyways and as the result is the same array, that is very good. The first option however is probably to slow, as it is a very large array. Even tho the code would be more readable. Thank you for your answer! – creyD Apr 8 at 8:33
• I also like the second solution. If you're not bound to the standard library, maybe also have a look at Python packages like pandas which are widely used in data analytics. – AlexV Apr 8 at 11:02
• @Alex Thank you :) – creyD Apr 8 at 14:56