有人能告诉我为什么这个 lambda 排序表达式不起作用吗?

发布于 2024-10-10 21:01:57 字数 1273 浏览 1 评论 0原文

我是 lambda 表达式的新手,刚刚遇到了一些我不明白的事情。

我有一个像这样的对象:

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

所以我尝试格式化字符串以在 lambda 中一起解析之前添加一个零:

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") 有什么不同?

另外,关于如何使其发挥作用有什么建议吗?

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

I have an object like so:

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 that works, sort of. The issues is that the hour is an int, so it's sometimes not 2 digits, resulting in a sort like so:

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:

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 try formatting the string to add a zero before I parse together in the lambda:

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

But it won't compile. It tells me:

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

Huh? What is different between the plain .ToString() (with no format string) and .ToString("00") in this situation?

Also, any suggestions as to how to get this working?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

你的呼吸 2024-10-17 21:01:57

我不在电脑前,所以我无法解释第一个,但我会回避它:

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

更少的字符串创建,没有解析开销等;)

I'm not at a PC so I can't explain the first, but I'd sidestep 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 string creations, no parsing overheads, etc ;)

南薇 2024-10-17 21:01:57

原因是因为它不是按顺序排序而是作为字符串排序。您需要创建一个比较器来比较日期。查看排序 - 以 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() 引起的异常的编译问题。

The reason is because it's not sorting ordinally but as a string. You need to create a comparer to compare the dates. Look at the sort - anything starting with a 1 precedes anything starting with a 2, thus you'll 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)

Should sidestep the compilation issue regarding the exception caused by the ToString().

沒落の蓅哖 2024-10-17 21:01:57

我可以看到你上面的代码无论有没有格式化都工作得很好。我认为这种错误行为没有任何理由

 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
    }

I can see your code above working perfectly fine with and without formatting. I see no reason for such wrong behaviour

 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
    }
笑忘罢 2024-10-17 21:01:57

这是因为日期是以字符串形式进行比较的。

将 lambda 调用更改为如下:

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

It is because the dates are being compared in their String form.

Change your lambda call to as follows:

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")));
谁许谁一生繁华 2024-10-17 21:01:57

您可能会疯狂地创建一个返回 DateTime 的扩展方法,组合现有字段 - 然后对其进行排序。

所述逻辑也可以直接在排序表达式中使用,但是您不能使用扩展方法:)

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

You could get crazy and make an extension method that returns a DateTime, combining the existing fields - then just sort on that.

Said logic could also be used directly in the sort expression as well, but then you don't get to use an extension method :)

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

美胚控场 2024-10-17 21:01:57

感谢所有提供帮助的人。事实证明,问题是在原始类中,小时可以为空,如下所示:

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

错误消息在那里没有多大帮助,但每个人的工作示例都允许我追踪它。

Thanks to everyone who helped. As it turns out, the issue was that in the original class, the hour was are nullable, like so:

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 a generated class that is much larger than the example I gave here - I tried to shorten it up to clarify things, and ended up leaving out the relevant part.

Changing the sort to use the value of the nullable int works:

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

The error message wasn't much help there, but everyone's working examples allowed me to track it down.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文