简体   繁体   English

为什么我通过linq订购不起作用

[英]Why my ordering by linq does not work

Trying to order logs by logtype or by logType and thenBy DateTime but does not work.What am I missing? 尝试按日志类型或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();
        }
    }

Thanks for any suggestions 感谢您的任何建议

The problem is that false is ordered before true . 问题在于,在true之前将false排序。 Thus first in your order come those that are not Fatal. 因此,在您的订单中首先出现那些不是致命的。 Out of those first come those that are not Error etc. 首先出现那些不是Error等的错误。

You can use inequalities to make it work: 您可以使用不等式使其起作用:

x => x.LoggedType != LogType.Fatal

etc. 等等

or use OrderByDescending and ThenByDescending . 或使用OrderByDescendingThenByDescending

But I'd prefer to give an order of the enum: 但是我更喜欢列举一个枚举:

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

and then just use this value: 然后只需使用此值:

var orderedLogs = logs.OrderByDescending(x => x.LoggedType);

Both your logWarning and logError have LoggedType = LogType.Error ! 无论您logWarninglogErrorLoggedType = LogType.Error

Another point: you should implement/use an IComparer for LogType ... see MSDN at http://msdn.microsoft.com/en-us/library/8ehhxeaf.aspx 另一点:您应该为LogType实现/使用IComparer ...请参阅http://msdn.microsoft.com/zh-cn/library/8ehhxeaf.aspx上的 MSDN。

Bascially something like: 基本上是这样的:

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

You need to do something like: 您需要执行以下操作:

var orderedLogs = logs.GroupBy(l => l.LoggedType)
                    .OrderBy(g => g.Key)
                    .SelectMany(g => g.OrderByDescending(l => l.LoggedDateTime)).ToList();

You can sort the collection by the field LoggedType, then by the field LoggedDateTime in the following code: 您可以在以下代码中按LoggedType字段对集合进行排序,然后按LoggedDateTime字段对集合进行排序:

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

I think there will be sorting by integer representation of enum. 我认为会有枚举的整数表示排序。 So with your enum there will be Fatal, Error, Warn etc. Or you can use IComparer (from Yahia answer) for your own definition rules of comparison. 因此,对于您的枚举,将出现“致命”,“错误”,“警告”等信息。或者,您也可以使用IComparer(来自Yahia答复)来自己定义比较规则。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM