Reputation: 63
I have a List of Lists consisting of int
arrays:
(List<List<int[]>>)
I want to sort the list of lists based on the first index in the int
array in the first element of the lists.
My solution so far is:
List<List<int[]>> myList = new List<List<int[]>> { new List<int[]> { new int[] { 1, 5 }, new int[] { 2, 4 } }, new List<int[]> { new int[] { 3, 4 }, new int[] { 0, 1 } } };
myList.OrderByDescending(x => x.Max(y => y[0])).ToList();
In which the result is that the second list comes first and the first would come second.
But I don't like that one as performance is a critical point and I don't like to execute the Max
operation as it is useless.
So, is there a better way?
-
EDIT: I finished using:
myList.OrderByDescending(x => x[0][0]).ToList();
As proposed by CodeCaster in the comments. This one was faster in my code than the option proposed by Aldert. But his answer is worth viewing too.
Upvotes: 1
Views: 1113
Reputation: 4313
This is the answer you are looking for with a binary compare, it is fairly simple because it takes the first element out of the sublint and out of the array (as you where looking for).
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<List<int[]>> mainList = new List<List<int[]>>();
Random rand = new Random();
for (int i = 0; i < 30; i++)
{
List<int[]> subList = new List<int[]>();
int limj = rand.Next(5);
for (int j = 0; j < 5 + limj; j++)
{
int limk = rand.Next(5);
int[] arrayInt = new int[limk + 5];
for (int k = 0; k < limk + 5; k++)
{
arrayInt[k] = rand.Next(200);
}
subList.Add(arrayInt);
}
mainList.Add(subList);
}
mainList.Sort(new MaxComparer(false));
foreach (List<int[]> oneL in mainList)
{
foreach (int[] arrayList in oneL)
{
foreach (int i in arrayList) Console.Write(i + " ");
Console.Write("|");
}
Console.WriteLine();
}
}
public class MaxComparer : IComparer<List<int[]>>
{
bool order = false;
public MaxComparer(bool Order)
{
order = Order;
}
public int Compare(List<int[]> x, List<int[]> y)
{
return x[0][0].CompareTo(y[0][0]) * (order ? 1 : -1);
}
}
}
}
Upvotes: 0
Reputation: 2174
Is this what you are looking for?
var sortedList = myList.OrderBy(x => x.Select(y => y.Select(z => z).OrderBy(z => z))).ToList();
EDIT: I forgot to go one layer deeper. The error was caused because it wanted to order an arrayobject instead of its elements.
Upvotes: 0
Reputation: 4313
This code is sorting asc or desc depending on the order you pass to the comparer. It runs O*1 over the elements, to setup the structure to be able to compare. I would be interesting to know if it works faster for you (I do think only with very big trees). When you would sort all the inner lists already, you do not need to keep a helper dictionary, you can then take the last element.
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<List<int>> mainList = new List<List<int>>();
List<int> newList = new List<int>();
Random rand = new Random();
for (int i = 0; i < 30; i++)
{
int ra = rand.Next(200);
if (i % 5 == 0)
{
if (newList.Count > 0)
{
newList = new List<int>();
mainList.Add(newList);
}
}
newList.Add(ra);
}
mainList.Sort( new MaxComparer(mainList, false));
foreach (List<int> oneL in mainList)
{
foreach (int oneInt in oneL)
{
Console.Write(oneInt + " ");
}
Console.WriteLine();
}
}
public class MaxComparer : IComparer<List<int>>
{
bool order = false;
Dictionary<int, int> helper = new Dictionary<int, int>();
public MaxComparer(List<List<int>> sortList, bool Order)
{
order = Order;
foreach (List<int> oneL in sortList)
{
int max = int.MinValue;
foreach (int oneInt in oneL)
{
if (max < oneInt) max = oneInt;
}
helper.Add(oneL.GetHashCode(), max);
}
}
public int Compare(List<int> x, List<int> y)
{
return helper[x.GetHashCode()].CompareTo(helper[y.GetHashCode()]) * (order ? 1:-1);
}
}
}
}
Upvotes: 1