HdG
HdG

Reputation: 63

Method to sort List of Lists based on Sublist

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

Answers (3)

Aldert
Aldert

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

Immorality
Immorality

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

Aldert
Aldert

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

Related Questions