Mico
Mico

Reputation: 117

lambda string order by dates with number

How to sort this?

I have List of string with values like this

11-03-2013
11-03-2013 -Count=2
11-03-2013 -count=1

11-04-2013 -Count=1
11-04-2013 -Count=2
11-04-2013

Output should be, The one without the count should be on the last and the top most should be 1 followed by 1 and dates should be ordered by ascending.

11-03-2013 -Count=2
11-03-2013 -count=1
11-03-2013

11-04-2013 -Count=2
11-04-2013 -Count=1
11-04-2013

I tried this code but this is sorting this by descending

var  edates= edates.OrderBy(e => e.Replace("-count=1", string.Empty).Replace("-count=2", string.Empty)).ToList(); 

I know that a simple class with properties can do the trick but doing that so would need to change other methods which would require a lot of work.

Regards

Upvotes: 3

Views: 1084

Answers (5)

crthompson
crthompson

Reputation: 15865

Here is @Guru Stron's solution in code

private static void sortList()
{
    var dates = getDates();
    var sorted = dates.OrderBy(f1).ThenByDescending(f2);
}

private static DateTime f1(string parse)
{
    return DateTime.Parse(parse.Substring(0, 10));
}

private static int f2(string parse)
{
    int sort;
    if (parse.Length > 10) int.TryParse(parse.Substring(18), out sort);
    else sort = 0;
    return sort;
}

Upvotes: 2

Guru Stron
Guru Stron

Reputation: 141895

it is because you compare strings not dates. Create two functions: first substrings date part and parses it and second substrings the count part and returns parsed count(or 0 if length < 11) and then yourList.OrderBy(s=> f1(s)).ThenByDescending(s=> f2(s))

Upvotes: 3

user2864740
user2864740

Reputation: 61875

The following should order as desired across different years and counts >= 10.

This won't be the "fastest" method (and it will most certainly not work with L2S/EF LINQ providers), but it should sort the given format correctly and fail-fast on invalid values. I would likely write the code like this (or use an IComparer with an equivalent setup) - mainly because it "reads simple" to me.

DateTime OrderableItem (string e) {
    var date = e.Substring(0, 10);
    return DateTime.ParseExact(date, "MM-dd-yyyy", CultureInfo.InvariantCulture)
}

int OrderableCount (string e) {
    var m = Regex.Match(e, @"-count=(\d+)$", RegexOptions.IgnoreCase);
    return m.Success
        ? int.Parse(m.Groups[1].Value)
        : 0;
}

var res = seq.OrderBy(OrderableDate)
             .ThenBy(OrderableCount);

I much prefer to take data, instead of excluding data.

Upvotes: 0

Joachim Isaksson
Joachim Isaksson

Reputation: 180917

You first need to order by the date, then by the rest of the string, descending;

    edates =
        edates.OrderBy(x => 
               DateTime.ParseExact(x.Substring(0, 10), "MM-dd-yyyy", 
               CultureInfo.InvariantCulture))
            .ThenByDescending(x => x.Substring(10))
            .ToList();

Upvotes: 1

Ahmad Mageed
Ahmad Mageed

Reputation: 96477

You ought to use a real class to simplify things and have a proper representation. That said, you can use the LINQ query syntax and take advantage of the let clause to store the result of splitting the text on a space and the equal symbol. If the split result has more than one element we can assume the count exists. Next, we order by the date (after parsing it) and then by parsing the count (descending).

Try this approach out:

string[] inputs = 
{
    "11-03-2013",
    "11-03-2013 -Count=2",
    "11-03-2013 -Count=1",
    "11-04-2013 -Count=1",
    "11-04-2013 -Count=2",
    "11-04-2013"
};

var query = from input in inputs
            let split = input.Split(' ', '=')
            let count = split.Length > 1 ? int.Parse(split[2]) : 0
            orderby DateTime.Parse(split[0]), count descending
            select input;

foreach (var item in query)
{
    Console.WriteLine(item);
}

Upvotes: 0

Related Questions