Can someone tell me why this lambda sort expression doesn't work?

I'm new to lambda expressions and just ran into something I don't understand.

I have an object like this:

class MyListItem { string date; //date in the format "2010-12-05" int Hour; //hour of day as an int } 

I have a list of these objects representing some dates and hours.

I want to sort this list by date and hour, so I try this:

 List<MyListItem> myList = new List<MyListItem>(); myList = getsomedata(); //populate list myList.Sort((a, b) => (a.date + a.Hour.ToString()).CompareTo(b.date + b.Hour.ToString())); 

and it works, sort of. The problems are that the hour is int, so sometimes it is not 2 digits, which leads to similar types:

 2010-12-05 1 2010-12-05 10 2010-12-05 11 2010-12-05 12 2010-12-05 13 2010-12-05 2 2010-12-05 21 2010-12-05 22 

I want it to be like this:

 2010-12-05 1 2010-12-05 2 2010-12-05 10 2010-12-05 11 2010-12-05 12 2010-12-05 13 2010-12-05 21 2010-12-05 22 

so I'm trying to format the string to add zero before parsing it together in lambda:

 ret.Sort((a, b) => (a.date + a.Hour.ToString("00")).CompareTo(b.date + b.Hour.ToString("00"))); 

But it will not compile. This tells me:

 Cannot convert lambda expression to type 'Systems.Collections.Generic.IComparer<MyListItem>' because it is not a delegate type. 

A? What is the difference between regular .ToString () (without a format string) and .ToString ("00") in this situation?

Also, any suggestions on how to do this?

+4
source share
6 answers

Thanks to everyone who helped. As it turned out, the problem was that in the original class the hour was zero, for example:

 class MyListItem { string date; //date in the format "2010-12-05" int? Hour; //hour of day as an int } 

The real class I'm using is the generated class, which is much larger than the example given here. I tried to shorten it to clarify the situation, and as a result left the corresponding part.

Changing the sort to use the value of the int zero feature:

 myList.Sort((a, b) => (a.date + a.Hour.Value.ToString("00")).CompareTo(b.date + b.Hour.Value.ToString("00"))); 

The error message did not help, but all working examples allowed me to track it.

0
source

I'm not on a PC, so I canโ€™t explain the first, but I would go around it:

 ret.Sort((a,b) => { int result = string.Compare(a.date,b.date); if(result==0) result = a.hour.CompareTo(b.hour); return result; }); 

Less line creation, no parsing overhead, etc .;)

+5
source

The reason is that it is not sorted in order, but as a string. You need to create a comparer to compare dates. Look at the sorting - everything starting from 1 precedes anything starting from 2, so you get: 1, 11, 111, 1111, 2, 22, 222, 222, 3, 33, 333, etc.

Try converting the resulting string to a date that should fix it.

 DateTime.ParseExact(a.date + hour.ToString("00"), "yyyy-MM-dd HH", CultureInfo.InvariantCulture) 

You should work around the compilation issue regarding the exception raised by ToString ().

+2
source

I see that your code above works fine with and without formatting. I see no reason for such misconduct.

  List<MyListItem> myList = new List<MyListItem>(); getsomedata(myList); //populate list myList.Sort((a, b) => (a.date + a.Hour.ToString("00")).CompareTo(b.date + b.Hour.ToString("00"))); private void getsomedata(List<MyListItem> items) { for (int i = 1; i < 30; i += 3) { items.Add(new MyListItem("2010-12-05", i)); } for (int i = 2; i < 30; i += 3) { items.Add(new MyListItem("2010-12-05", i)); } } class MyListItem { public MyListItem(string date, int hour) { this.date = date; this.Hour = hour; } public string date; //date in the format "2010-12-05" public int Hour; //hour of day as an int } 
+2
source

This is because dates are compared in their string form.

Change your lambda call like this:

 ret.Sort((a, b) => (DateTime.Parse(a.date + " " +a.Hour.ToString("00") + ":00:00").CompareTo(DateTime.Parse(b.date + " " + b.Hour.ToString("00") + ":00:00"))); 
+1
source

You can go crazy and create an extension method that returns a DateTime by combining existing fields and then just sorting by it.

The specified logic can also be used directly in the sort expression, but then you cannot use the extension method :)

public static DateTime GetDate (this MyListItem myListItem) {return DateTime.Parse (myListItem.date) .AddHours (myListItem.Hour); }

0
source

Source: https://habr.com/ru/post/1334551/


All Articles