0

Currently I have built an array of 1200 instances of the 'Element' class. Each one is populated automatically via its constructor (scraping data line by line from 9 different arrays (the arrays originate from 9 different text files)).

public class Element
{

    public int elementDay;
    public string elementMonth;
    public int elementYear;
    public string elementTime;
    public int elementTimestamp;
    public string elementRegion;
    public float elementLongitude;
    public float elementLatitude;
    public float elementMagnitude;
    public float elementDepth;
    public float elementIris_Id;

    public Element(int[] day, string[] month, int[] year, string[] time, int[] timestamp, string[] region, float[] longitude, float[] latitude, float[] magnitude, float[] depth, float[] iris_Id, ref int counter)
    {
        elementDay = day[counter];
        elementMonth = month[counter];
        elementYear = year[counter];
        elementTime = time[counter];
        elementTimestamp = timestamp[counter];
        elementRegion = region[counter];
        elementLongitude = longitude[counter];
        elementLatitude = latitude[counter];
        elementMagnitude = magnitude[counter];
        elementDepth = depth[counter];
        elementIris_Id = iris_Id[counter];
        counter++;
    }

public static void CreateElementList(Element[] arrayElements, int[] day, string[] month, int[] year, string[] time, int[] timestamp, string[] region, float[] longitude, float[] latitude, float[] magnitude, float[] depth, float[] iris_Id, ref int counter)
    {
        for (int i = 0; i < 1200; i++)
        {
            arrayElements[i] = new Element(day, month, year, time, timestamp, region, longitude, latitude, magnitude, depth, iris_Id, ref counter);
        }
    }

Right now I need to find a way of sorting these objects by certain properties. A working example of what I want is: Array.Sort(arrayElements, delegate (Element x, Element y) { return y.elementDay.CompareTo(x.elementDay); });

However I cannot use this as it is an in-built function. I'm trying to implement a Quicksort algorithm to sort these objects by 'day' but I do not know if it is possible to do such a thing with an array of elements as I only know how to do this with a simple integer array. The end goal is to be able to sort by any of the properties and for the entire array of elements to be sorted with respect to the chosen property.

Please keep in mind this is homework, so please do not give me the full solution, I mainly want to know if it is possible/worth my time, or should I simply try another approach?

James K
  • 11
  • 2
  • 2
    What are you really asking? Is it possible? Of course it is. Is it worth your time? Depends if it gives you marks for your course I guess. If you want to have a go at writing it, people here will help, but otherwise this is very vague and too broad. – DavidG Apr 10 '17 at 13:54
  • Please read this article http://stackoverflow.com/questions/14336416/using-icomparer-for-sorting – Andrey Belykh Apr 10 '17 at 13:57

1 Answers1

0

A skeleton of how you normally implement a sort:

public static void MySort<T>(IList<T> list, Comparison<T> comparison = null)
{
    if (comparison == null)
    {
        comparison = Comparer<T>.Default.Compare;
    }

    // ** Your sort algorithm goes here **

    // To compare two elements do it like:

    // Compare first and last element
    int cmp = comparison(list[0], list[list.Count - 1]);
    if (cmp < 0)
    {
        Console.WriteLine("first < last");
    }
    else if (cmp == 0)
    {
        Console.WriteLine("first == last");
    }
    else
    {
        Console.WriteLine("first > last");
    }
}

There is no sort algorithm there, but you can see how you can compare two elements, how the default Comparer<> is obtained normally by Array.Sort and similar methods, and how to obtain a Comparison<T> from a Comparer<>.

Then:

var elements = new[]
{
    new Element { elementDay = 15, elementMonth = 3, elementYear = 2017 },
    new Element { elementDay = 14, elementMonth = 3, elementYear = 2017 },
    new Element { elementDay = 13, elementMonth = 3, elementYear = 2016 },
};

MySort(elements, (x, y) => x.elementDay.CompareTo(y.elementDay));

Now... What if you want to sort by different fields, chaining them? (elementYear, then elementMonth and then elementDay for example)?

A "chained" comparison creator is (one of) the solution(s) :-)

public class MultiComparison
{
    private MultiComparison()
    {
    }

    // Create a singole comparison from an array of comparisons,
    // this comparison is the "chaining" of all the comparisons
    public static Comparison<T> Create<T>(params Comparison<T>[] comparisons)
    {
        if (comparisons == null || comparisons.Length == 0)
        {
            throw new ArgumentException("comparisons");
        }

        // Single comparison == it is already the comparison we can return
        if (comparisons.Length == 1)
        {
            return comparisons[0];
        }

        // We clone the array so that the caller of Create can't modify it 
        // behind the scene.
        comparisons = (Comparison<T>[])comparisons.Clone();

        // We return a method that will use all the comparisons,
        // stopping at the first comparison that gives a result != 0
        Comparison<T> comparison = (x, y) =>
        {
            for (int i = 0; i < comparisons.Length; i++)
            {
                int cmp = comparisons[i](x, y);

                if (cmp != 0)
                {
                    return cmp;
                }
            }

            return 0;
        };

        return comparison;
    }
}

Use it like:

MySort(
    elements, 
    MultiComparison.Create<Element>(
        (x, y) => x.elementYear.CompareTo(y.elementYear),
        (x, y) => x.elementMonth.CompareTo(y.elementMonth),
        (x, y) => x.elementDay.CompareTo(y.elementDay)
));
xanatos
  • 109,618
  • 12
  • 197
  • 280