title: Sort groups based on values within groups
body: <p>I am trying to sort an array that contains logical groups of people, and the people's scores.</p>
  
  <pre><code>Name   | Group | Score
  ----------------------
  Alfred |     1 |     3
  Boris  |     3 |     3
  Cameron|     3 |     1
  Donna  |     1 |     2
  Emily  |     2 |     2
  </code></pre>
  
  <p>The people should be sorted by group, based on the lowest score in the group. Therefore, group 3 is first, because it contains the person with the lowest score. Then the people in group 1 because it has the person with the next lowest score (and a lower group number than group 2).</p>
  
  <p>So the result would be: Cameron, Boris, Donna, Alfred, Emily</p>
  
  <p>I have accomplished this, but I am wondering if there is a better way of doing it. I receive an array, and end up sorting the array in the correct order.</p>
  
  <p>I use LINQ (mostly obtained from <a href="https://stackoverflow.com/questions/5013710/linq-order-by-group-by-and-order-by-each-group">Linq order by, group by and order by each group?</a>) to create a target sorting array that maps where a person should be, compared to where they currently are in the array.</p>
  
  <p>I then use Array.Sort using my target sorting array, but the array the LINQ statement creates is "reversed" in terms of indices and values, so I have to reverse the indices and values (not the order).</p>
  
  <p>I have attached my code below. Is there a better way of doing this?</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  
  namespace Sorter
  {
      class Program
      {
          static void Main(string[] args)
          {
              // Sample person array.
              // Lower score is better.
              Person[] peopleArray = new Person[]
              {
                  new Person { Name = "Alfred", Group = "1", Score = 3, ArrayIndex = 0 },
                  new Person { Name = "Boris", Group = "3", Score = 3, ArrayIndex = 1 },
                  new Person { Name = "Cameron", Group = "3", Score = 1, ArrayIndex = 2 },
                  new Person { Name = "Donna", Group = "1", Score = 2, ArrayIndex = 3 },
                  new Person { Name = "Emily", Group = "2", Score = 2, ArrayIndex = 4 }
              };
  
              // Create people list. 
              List&lt;Person&gt; peopleModel = peopleArray.ToList();
  
              // Sort the people based on the following:
              // Sort people into groups (1, 2, 3)
              // Sort the groups by the lowest score within the group.
              // So, the first group would be group 3, because it has the
              // member with the lowest score (Cameron with 1).
              // The people are therefore sorted in the following order:
              //  Cameron, Boris, Donna, Alfred, Emily
              int[] targetOrder = peopleModel.GroupBy(x =&gt; x.Group)
                                             .Select(group =&gt; new
                                             {
                                                 Rank = group.OrderBy(g =&gt; g.Score)
                                             })
                                             .OrderBy(g =&gt; g.Rank.First().Score)
                                             .SelectMany(g =&gt; g.Rank)
                                             .Select(i =&gt; i.ArrayIndex)
                                             .ToArray();
  
              // This will give the following array:
              // [2, 1, 3, 0, 4]
              // I.e: Post-sort, 
              //  the person who should be in index 0, is currently at index 2 (Cameron).
              //  the person who should be in index 1, is currently at index 1 (Boris).
              //                 etc.
  
              // I want to use my target array to sort my people array.
  
              // However, the Array.sort method works in the reverse.
              // For example, in my target order array:  [2, 1, 3, 0, 4]
              //    person currently at index 2 should be sorted into index 0.
              // I need the following target order array: [3, 1, 0, 2, 4], 
              //    person currently at index 0, should be sorted into index 3
              // So, "reverse" the target order array.
              int[] reversedArray = ReverseArrayIndexValue(targetOrder);
  
              // Finally, sort the base array.
              Array.Sort(reversedArray, peopleArray);
  
              // Display names in order.
              foreach (var item in peopleArray)
              {
                  Console.WriteLine(item.Name);
              }
  
              Console.Read();
          }
  
          /// &lt;summary&gt;
          /// "Reverses" the indices and values of an array.
          /// E.g.: [2, 0, 1] becomes [1, 2, 0].
          /// The value at index 0 is 2, so the value at index 2 is 0.
          /// The value at index 1 is 0, so the value at index 0 is 1.
          /// The value at index 2 is 1, so the value at index 1 is 2.
          /// &lt;/summary&gt;
          /// &lt;param name="target"&gt;&lt;/param&gt;
          /// &lt;returns&gt;&lt;/returns&gt;
          private static int[] ReverseArrayIndexValue(int[] target)
          {
              int[] swappedArray = new int[target.Length];
  
              for (int i = 0; i &lt; target.Length; i++)
              {
                  swappedArray[i] = Array.FindIndex(target, t =&gt; t == i);
              }
  
              return swappedArray;
          }
      }
  }
  </code></pre>