Reputation: 101
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);
}
}
Upvotes: 1
Views: 115
Reputation: 23732
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();
Upvotes: 1
Reputation: 186668
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();
Upvotes: 1