简体   繁体   English

IComparer没有正确排序

[英]IComparer not sorting properly

I am currently working on a project where I need to sort entries of a list of tuples according to a certain scheme. 我目前正在开发一个项目,我需要根据某个方案对元组列表的条目进行排序。 For that purpose I wrote a simple IComparer: 为此我写了一个简单的IComparer:

private class OrderComparer : IComparer<Tuple<string, DateTime, string>>
{
    public int Compare(Tuple<string, DateTime, string> x, Tuple<string, DateTime, string> y)
    {
        var yearX = x.Item1.Substring(x.Item1.Length - 2);
        var yearY = y.Item1.Substring(y.Item1.Length - 2);
        var monthX = x.Item1.Substring(x.Item1.Length - 4, 2);
        var monthY = y.Item1.Substring(y.Item1.Length - 4, 2);
        var numberX = x.Item1.Substring(1, x.Item1.Length - 5);
        var numberY = y.Item1.Substring(1, y.Item1.Length - 5);


        if (!yearX.Equals(yearY))
        {
            return Convert.ToInt32(yearX).CompareTo(Convert.ToInt32(yearY));
        }
        if (!monthX.Equals(monthY))
        {
            return Convert.ToInt32(monthX).CompareTo(Convert.ToInt32(monthY));
        }
        return Convert.ToInt32(numberX).CompareTo(Convert.ToInt32(numberY));
    }
}

the reading of yearX/Y, monthX/Y and numberX/Y works correctly as found in a debugging session. 读取yearX / Y,monthX / Y和numberX / Y可以正常工作,如在调试会话中找到的那样。

The problem I am now facing is that it sorts correctly after the year and month but not the number. 我现在面临的问题是它在年和月之后正确排序,而不是数字。 I verified, that 我验证了那个

return Convert.ToInt32(numberX).CompareTo(Convert.ToInt32(numberY));

returns the correct value (1 when numberX > numberY). 返回正确的值(numberX> numberY时为1)。

I call the sort method using the following code: 我使用以下代码调用sort方法:

var dataList = data as IList<Tuple<string, DateTime, string>> ?? data.ToList();
dataList.ToList().Sort(new OrderComparer());

where data is an IEnumerable. 其中数据是IEnumerable。

I am sorry for this rather simple question but I am completely stuck and I don't see any error in my implementation. 我很抱歉这个相当简单的问题,但我完全陷入困境,我没有看到我的实施中有任何错误。 Kind regards 亲切的问候

Lukas EDIT: since sample data is needed. Lukas编辑:因为需要样本数据。 Here's the data the algorithm fails: B080114, B140114, B100114, B160114, B130114 这是算法失败的数据:B080114,B140114,B100114,B160114,B130114

this is the actual result after sorting 这是排序后的实际结果

It's hard to guess what the problem is since you don't provide sample data. 由于您不提供样本数据,因此很难猜出问题所在。

I assume you should replace 我认为你应该更换

var numberX = x.Item1.Substring(1, x.Item1.Length - 5);

with: 有:

var numberX = x.Item1.Substring(0, x.Item1.Length - 6);

(don't forget to modify the line for numberY as well). (别忘了修改numberY的行)。 Since strings start with index 0 (and you probably only grab the last digit). 因为字符串以索引0开头(你可能只抓住最后一位数字)。

Although I would advice you to simply parse the string to a DateTime object (there is a builtin method for this, that will probably suffice), and then use the default comparable of the DateTime object. 虽然我建议你简单地将string解析为DateTime对象(有一个内置的方法,这可能就足够了),然后使用默认的DateTime对象。 This will improve speed as well since this method will parse string objects on average O(n log n) times [and worst case O(n^2) times] instead of O(n) times 这也将提高速度,因为此方法将平均解析string对象O(n log n)次[和最坏情况O(n ^ 2)次]而不是O(n)次

Your problem is in this line: 你的问题在于这一行:

dataList.ToList().Sort(new OrderComparer())

the Sort method as you know doesn't return the sorted version but operates on the original list. 如您所知, Sort方法不会返回已排序的版本,而是在原始列表上运行。 Here however the list it is sorting is not dataList but dataList.ToList() which is not the same item. 然而,这里排序的列表不是dataList而是dataList.ToList() ,它不是同一个项目。

So it sorts dataList.ToList() in place but since you have no reference to it it is thrown away and you are left with the unmodified dataList instead. 因此它将dataList.ToList()排序到位,但由于您没有引用它,因此它将被丢弃,而您将保留未修改的dataList

The best fix would probably be to change the preceding line to: 最好的解决方法可能是将前一行更改为:

var dataList = data.ToList();

So rather than checking if it is a suitable IList and so on we are just doing a ToList() to make sure we have a List so the next line can then be: 因此,不是检查它是否是一个合适的IList等等,我们只是做一个ToList()来确保我们有一个List,所以下一行可以是:

dataList.Sort(new OrderComparer());

This will now work on the correct list and hopefully thus do what you want. 现在,这将在正确的列表上工作,并希望这样做你想要的。

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

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