Может кто-нибудь сказать мне, почему это выражение лямбда-сортировки не работает? - PullRequest
4 голосов
/ 06 января 2011

Я новичок в лямбда-выражениях и столкнулся с чем-то, чего я не понимаю.

У меня есть такой объект:

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

}

У меня есть список этих объектов, представляющих некоторые даты и часы.

Я хочу отсортировать этот список по дате и часам, поэтому я пытаюсь это сделать:

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()));

и это работает, вроде. Проблема в том, что час - это int, поэтому иногда он не состоит из 2 цифр, в результате получается что-то вроде:

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

Я хочу, чтобы это было похоже на

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

поэтому я пытаюсь отформатировать строку, чтобы добавить ноль, перед тем как выполнить синтаксический анализ в лямбда-выражении:

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

Но это не скомпилируется. Это говорит мне:

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

А? Чем отличаются обычные .ToString () (без форматной строки) и .ToString ("00") в этой ситуации?

Кроме того, какие-либо предложения относительно того, как заставить это работать?

Ответы [ 6 ]

5 голосов
/ 06 января 2011

Я не за компьютером, поэтому не могу объяснить первое, но я бы обошел стороной:

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

Меньше создания строк, никаких накладных расходов на анализ и т. Д .;

2 голосов
/ 06 января 2011

Я вижу, что ваш код выше работает отлично и без форматирования.Я не вижу причин для такого неправильного поведения

 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 голосов
/ 06 января 2011

Причина в том, что это не обычная сортировка, а строка. Вам нужно создать компаратор для сравнения дат. Посмотрите на сортировку - все, что начинается с 1, предшествует любому, начинающемуся с 2, поэтому вы получите: 1, 11, 111, 1111, 2, 22, 222, 222, 3, 33, 333 и т. Д.

Попробуйте преобразовать полученную строку в дату, которая должна это исправить.

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

Следует обойти проблему компиляции относительно исключения, вызванного ToString ().

1 голос
/ 06 января 2011

Это потому, что даты сравниваются в строковой форме.

Измените лямбда-вызов следующим образом:

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")));
0 голосов
/ 06 января 2011

Спасибо всем, кто помог. Как выясняется, проблема заключалась в том, что в исходном классе время было обнуляемым, например:

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

}

Реальный класс, который я использую, это сгенерированный класс, который намного больше, чем пример, который я привел здесь - я попытался сократить его, чтобы прояснить ситуацию, и закончил тем, что пропустил соответствующую часть.

Изменение сортировки для использования значения обнуляемого типа int:

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

Сообщение об ошибке не сильно помогло, но все рабочие примеры позволили мне отследить его.

0 голосов
/ 06 января 2011

Вы можете сойти с ума и создать метод расширения, который возвращает DateTime, объединяя существующие поля, а затем просто сортировать по ним.

Указанную логику также можно использовать непосредственно в выражении сортировки, но тогда вы не сможете использовать метод расширения:)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...