Почему мой заказ по linq не работает - PullRequest
0 голосов
/ 23 сентября 2011

Попытка упорядочить журналы по типу журнала или по типу logType, а затем по DateTime, но не работает. Чего мне не хватает?

      public enum LogType
    {
        Fatal,
        Error,
        Warn,
        Info,
        Debug,
        None,
    }
    public class Log
    {
        public DateTime LoggedDateTime { get; set; }
        public string Message { get; set; }
        public LogType LoggedType { get; set; }
        public override string ToString()
        {
            return string.Format("LogType: {0} Datetime: {1} Message: {2}", LoggedType, LoggedDateTime, Message);
        }
    }
    class Program
    {
        static void Main()
        {
            var logFatal = new Log
                               {
                                   LoggedDateTime = new DateTime(2011, 2, 22),
                                   Message = "Hi am a Fatal message",
                                   LoggedType = LogType.Fatal
                               };

            var logInfo = new Log
            {
                LoggedDateTime = new DateTime(2013, 2, 22),
                Message = "Hi I am a Info message",
                LoggedType = LogType.Info
            };

            var logError = new Log
            {
                LoggedDateTime = new DateTime(2010, 2, 22),
                Message = "Hi I am a Error message",
                LoggedType = LogType.Error
            };

            var logWarning = new Log
            {
                LoggedDateTime = new DateTime(2014, 2, 22),
                Message = "Hi I am a Warning message",
                LoggedType = LogType.Warn
            };
            List<Log> logs = new List<Log> { logWarning, logError, logInfo, logFatal };

            Console.WriteLine("Not Ordered");
            Console.WriteLine("");
            logs.ForEach(x=>Console.WriteLine(x.LoggedType));



            var orderedLogs = logs.OrderBy(x => x.LoggedType == LogType.Fatal)
                .ThenBy(x => x.LoggedType == LogType.Error)
                .ThenBy(x => x.LoggedType == LogType.Warn)
                .ThenBy(x => x.LoggedDateTime).ToList();

            Console.WriteLine("Ordered by logType fatal first and NOT WORKING");
            Console.WriteLine("");

            orderedLogs.ForEach(x=>Console.WriteLine(x.LoggedType));

            Console.WriteLine("");
            Console.WriteLine("Ordered by logType fatal first and NOT WORKING");//NOT WORKING
            List<Log> orderedFatal = logs.OrderBy(x => x.LoggedType == LogType.Fatal).ToList();
            orderedFatal.ForEach(x => Console.WriteLine(x.LoggedType));

            Console.WriteLine("");
            Console.WriteLine("Sorted by datetime AND WORKS"); //THIS IS THE ONLY ONE THAT WORKS
            logs.Sort((x,y)=>x.LoggedDateTime.CompareTo(y.LoggedDateTime));
            logs.ForEach(x => Console.WriteLine(x.LoggedDateTime));


            Console.Read();
        }
    }

Спасибо за любые предложения

Ответы [ 4 ]

4 голосов
/ 23 сентября 2011

Проблема в том, что false заказан раньше true.Таким образом, сначала в вашем порядке идут те, которые не являются фатальными.Из тех, которые первыми, приходят те, которые не являются ошибками и т. Д.

Вы можете использовать неравенства, чтобы заставить его работать:

x => x.LoggedType != LogType.Fatal

и т. Д.

или использовать OrderByDescendingThenByDescending.

Но я бы предпочел указать порядок перечисления:

public enum LogType : int
    {
        Fatal = 5,
        Error = 4,
        Warn = 3,
        Info = 2,
        Debug = 1,
        None = 0,
}

, а затем просто использовать это значение:

var orderedLogs = logs.OrderByDescending(x => x.LoggedType);
0 голосов
/ 23 сентября 2011

Вы можете отсортировать коллекцию по полю LoggedType, затем по полю LoggedDateTime в следующем коде:

var orderedLogs = logs.OrderBy(x => x.LoggedType) // not x => x.LoggedType == LogType.Fatal
    .ThenBy(x => x.LoggedDateTime).ToList();

Я думаю, что будет сортировка по целочисленному представлению enum.Так что с вашим перечислением будут Fatal, Error, Warn и т. Д. Или вы можете использовать IComparer (из ответа Yahia) для ваших собственных определений правил сравнения.

0 голосов
/ 23 сентября 2011

Вам нужно сделать что-то вроде:

var orderedLogs = logs.GroupBy(l => l.LoggedType)
                    .OrderBy(g => g.Key)
                    .SelectMany(g => g.OrderByDescending(l => l.LoggedDateTime)).ToList();
0 голосов
/ 23 сентября 2011

Оба ваших logWarning и logError имеют LoggedType = LogType.Error!

Еще один момент: вы должны реализовать / использовать IComparer для LogType ... см. MSDNв http://msdn.microsoft.com/en-us/library/8ehhxeaf.aspx

В основном что-то вроде:

public class LogComparer : IComparer<Log>
{
    public int Compare(Log x, Log y)
    {
        if ( x == y ) return 0;
        if ( x.LoggedType == y.LoggedType ) return 0;
        if ( x.LoggedType == LogType.Fatal ) return 1;
        if ( y.LoggedType == LogType.Fatal ) return -1;
        // etc.
    }
}

// Usage similar to this
logs.OrderBy(x => x, new LogComparer());
...