1

Given a list/array of objects containing some other objects, I'm looking to sort by using one of the parameters. For example, if I have a multi-dimensional array of ints and I want to sort by their midpoint.

The way I'm doing it is to create an anonymous object containing 1. the midpoint and 2. a list of the 2 ints for each entry. Then enlist these objects and use reflection to access and sort by the midpoint parameter.

Is there a more standard approach to this problem? It's a bit clumsy because I have to create a dummy and clear the anonymous list object in order to do it.

class Program
{
    static void Main(string[] args)
    {
        int[,] input = new int[,] { { 5, 6 }, { 0, 1 }, { 2, 20 } };

        var itemList = new []{ 
          new { sortVar = 0.1f, item = new List<int>() } }.ToList();

        itemList.Clear();

        for(int i=0; i<input.GetLength(0); i++)
        {
            List <int> temp = new List<int> (new int[] { input[i,0], input[i, 1] });

            var item = new { 
              sortVar = float.Parse((input[i,0]+input[i,1]).ToString())/2,
              item = temp };

            itemList.Add(item);
        }

        var itemList2 = itemList.OrderBy(x => x.sortVar);
    }
}
1
  • 6
    Code-review. Commented Sep 5, 2017 at 7:39

2 Answers 2

1

A short linq version of your approach would be to use the Average method directly in the OrderBy clause (if you are inclined to use a 2-D List):

List<List<int>> input_List = new List<List<int>> 
{
    new List<int>{ 5, 6 }, 
    new List<int>{ 0, 1 }, 
    new List<int>{ 2, 20 } 
};

var output = input_List.OrderBy(x=>x.Average()).ToList();   

EDIT:

If you need to order it by the median you can use this expression:

var output = input_List.OrderBy(x=>x.OrderBy(y=>y).ElementAt(x.Count / 2)).ToList();    
Sign up to request clarification or add additional context in comments.

7 Comments

Mid point is not Average but Median - middle item in the sorted array: [1, 2, 100] -> 2; [1, 2, 4, 100] -> (2 + 4) / 2 == 3
@DmitryBychenko looking at OP's code he is not calculating the median but the mean: float.Parse((input[i,0]+input[i,1]).ToString())/2 when I try his code sortVar has values of 0.5, 5.6 and 11. which is definetely not the median
in case array has 1 or 2 items, median equals to average
@DmitryBychenko although the calculation seems still like mean to me :) I added a median version to my post. Thank you for emphasizing.
Ahhh ok got it. Thanks!
|
1

I suggest changing 2D array into jagged one (array of array):

   int[][] input = new int[][] { 
     new int[]{ 5,  6 }, 
     new int[]{ 0,  1 }, 
     new int[]{ 2, 20 } }; 

And extract the criterium (MidPoint) as a method

   private static double MidPoint(IEnumerable<int> value) {
      int[] sorted = value.OrderBy(item => item).ToArray(); 

      // / 2.0: we don't want integer division: (1 + 4) / 2 == 2 when (1 + 4) / 2.0 == 2.5
      return sorted.Length % 2 == 0
        ? (sorted[sorted.Length / 2 - 1] + sorted[sorted.Length / 2]) / 2.0
        : sorted[sorted.Length / 2];
    } 

Tnen if you want to sort in place use Array class:

 // input will be sorted 
 Array.Sort(input, (a, b) => MidPoint(a).CompareTo(MidPoint(b)));

If you want to create a new sorted array:

 // we'll have to arrays: initial (unsorted) input, and sorted sortedInput
 var sortedInput = input
   .OrderBy(line => MidPoint(line))
   .ToArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.