1

Assuming I have a list of numbers, which could be any amount, realistically over 15.

I want to separate that list of numbers into three groups depending on their size, small, medium, and large for instance.

What is the best way of achieving this?

I've written out the below, is it necessary to make my own function as per below, or is there anything existing that I can utilise in .NET?

  public static List<int> OrderByThree (List<int> list)
            {
                list.Sort();
                int n = list.Count();
                int small = n / 3;
                int medium = (2 * n) / 3;
                int large = n;
    // depending if the number is lower/higher than s/m/l,
 // chuck into group via series of if statements

                return list;
            }

Example Say I have a list of numbers, 1-15 for instance, I want 1-5 in small, 6-10 in medium and 11-15 in large. However I won't know the amount of numbers at the start, no dramas, using list.count I was hoping to divide for my own function.

JammAndTea
  • 195
  • 1
  • 8
  • 2
    errr... `GroupBy`? Obviously you still need to determine the limits. Alternatively, could you just do `list.Take(list.Count() / 3)` since you have already sorted it? – BradleyDotNET Oct 20 '15 at 17:14
  • 1
    Also, GroupBy (or any other approach that generates three lists) won't return a `List`, but rather 3 `List` in some representation. Or do you want to return a single list, with the sorting based only on "small, medium, large" rather than the actual numeric value? – Eric J. Oct 20 '15 at 17:15
  • if you already have it sorted you already have those groups by their indizes (small,medium,large) ;) – Random Dev Oct 20 '15 at 17:16
  • Can you give an example? It's not completely obvious if plan to compare `small`, `medium`, and `large` against the values, or the indexes. – juharr Oct 20 '15 at 17:18
  • You r function is returning the same list you passed it just sorted. To group you need to either split the list into three lists or return two indexes. You assume the smallest group starts at index zero. So you need to return the index number between the smallest and medium items, and the index between the medium and largest items. – jdweng Oct 20 '15 at 17:18
  • Good plan, will do, thanks jdweng – JammAndTea Oct 20 '15 at 17:21
  • split it to 3 parts. http://stackoverflow.com/questions/438188/split-a-collection-into-n-parts-with-linq – M.kazem Akhgary Oct 20 '15 at 17:27
  • Nice, thanks for that. – JammAndTea Oct 20 '15 at 17:33

2 Answers2

6

Since you have the list sorted already, you can use some LINQ to get the results. I'm assuming a right-closed interval here.

list.Sort();
int n = list.Count();
var smallGroup = list.TakeWhile(x => (x <= n / 3)).ToList();
var middleGroup = list.Skip(smallGroup.Count).TakeWhile(x => (x <= (2 * n) / 3)).ToList();
var largeGroup = list.Skip(smallGroup.Count + middleGroup.Count).ToList();

EDIT As Steve Padmore commented, you probably will want to return a list of lists (List<List<int>>) from your method, rather than just List<int>.

return new List<List<int>> { smallGroup, middleGroup, largeGroup };
Kapol
  • 6,383
  • 3
  • 21
  • 46
3

This would be a simple way of doing it:

var result = list.GroupBy (x => 
{
    if(x <= small) return 1;
    if(x <= medium) return 2;
    return 3;
});

Or:

var result = list.GroupBy (x => x <= small ? 1 : x <= medium ? 2 : 3);

(This does not require the list to be sorted)

Magnus
  • 45,362
  • 8
  • 80
  • 118