Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a variable in the x y sort

Tags:

c#

.net

asp.net

I have the following right now:

switch (Mysort)
{
    case "reqDate":
        lstDMV.Sort((x, y) => DateTime.Compare(x.RequestDate, y.RequestDate));
        break;
    case "notifDate":
        lstDMV.Sort((x, y) => DateTime.Compare(x.NotifDate, y.NotifDate));
        break;
    case "dueDate":
        lstDMV.Sort((x, y) => String.Compare(x.TargetDateShort, y.TargetDateShort));
        break;
    case "days":
        lstDMV.Sort((x, y) => x.DaysLapsed.CompareTo(y.DaysLapsed));
        break;
}

I want to get rid of the case statement and just do something like:

lstDMV.Sort((x, y) => String.Compare(x.MySort, y.MySort));

The case statement is HUGE and it will really cut down on readability. But because MySort is not contained in lstDMV it's not working. Is there another way I can substitute it in?

I will of course change the text to make sure MySort variable values match exactly to the lstDMV property names.

i've also tried the following with no luck :(

 if (sort != "")
            {
                string xsort, ysort;
                xsort = "x." + sort;
                ysort = "y." + sort;

                lstDMV.Sort((x, y) => String.Compare(xsort, ysort));
            }
like image 664
Madam Zu Zu Avatar asked Jan 18 '13 16:01

Madam Zu Zu


2 Answers

A dictionary with comparer Func's

    public class YourDataClass {
        public string RequestDate { get; set; }
        public string NotifDate { get; set; }
        .
        .
        .
    }

    public class Sorter<T> where T : YourDataClass {
        private Dictionary<string, Func<T, T, int>> actions =
            new Dictionary<string, Func<T, T, int>> {
                {"reqDate", (x, y) => String.Compare(x.RequestDate, y.RequestDate)},
                {"notifDate", (x, y) => String.Compare(x.NotifDate, y.NotifDate)}
            };

        public IEnumerable<T> Sort(IEnumerable<T> list, string howTo) {
            var items = list.ToArray();
            Array.Sort(items, (x, y) => actions[howTo](x, y));
            return items;
        }
    }

    public void Sample() {
        var list = new List<YourDataClass>();
        var sorter = new Sorter<YourDataClass>();
        var sortedItems = sorter.Sort(list, "reqDate");
    }
like image 118
lboshuizen Avatar answered Nov 02 '22 11:11

lboshuizen


Well you could use reflection, assuming all your property types implement IComparable:

private class Test
{
    public DateTime RequestDate { get; set; }

    public string Name { get; set; }
}

private static void Main(string[] args)
{
    var list = new List<Test>
    {
        new Test
        {
            RequestDate = new DateTime(2012, 1, 1),
            Name = "test"
        },
        new Test
        {
            RequestDate = new DateTime(2013, 1, 1),
            Name = "a_test"
        },
    };

    string mySort = "RequestDate";
    list.Sort((x, y) =>
        {
            // Gets the property that match the name of the variable
            var prop = typeof(Test).GetProperty(mySort);

            var leftVal = (IComparable)prop.GetValue(x, null);
            var rightVal = (IComparable)prop.GetValue(y, null);

            return leftVal.CompareTo(rightVal);
        });

    Console.Read();
}

I wouldn't recommend that, as even if there might be less code, it's less readable than the switch you currently have.

like image 39
ken2k Avatar answered Nov 02 '22 09:11

ken2k