2014-03-05 71 views
0

我目前正在研究一個項目,我需要按照某種方案對元組列表中的條目進行排序。 爲此我寫了一個簡單的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)); 
    } 
} 

在調試會話發現yearX/Y,monthX/Y和numberX/Y的讀數正常工作。

我現在面臨的問題是它在年份和月份之後正確排序,而不是數字。 我驗證,即

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

返回正確的值(1當numberx>相numberY)。

我請使用以下代碼的排序方法:

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

,其中數據是一個IEnumerable。

我很抱歉,這個相當簡單的問題,但我完全卡住了,我沒有看到我的執行中的任何錯誤。 親切的問候

Lukas 編輯:由於樣本數據是必要的。這裏的算法失敗的數據: B080114, B140114, B100114, B160114, B130114

這是排序

+1

爲了不使用基於'String'的複雜排序操作,爲什麼不首先將它解析爲'DateTime',這可能會提高速度......'DateTime'具有內建的可比性。然後,你可以排序,而無需實施自己的比較。 –

+0

你可以提供一些它失敗的示例數據(我們可以複製並粘貼來重現你的問題)? – Chris

+0

剛剛編寫了一些測試數據,它似乎適用於我...我的測試數據在第二部分和第三部分中有不相關的數據,第一部分有字符串'{「010114」,「020114」,「010214 「,」020314「,」010113「,」010213「,」020113「}'。您的比較器按第5位和第6位(年),第3位和第4位(月)和第2位(數字)正確排序。這意味着你沒有展示或解釋正確的東西。例如,數字意味着只是字符串的第二個數字? – Chris

回答

1

您的問題在於此行:

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

你知道不返回排序的版本,但原來的名單上操作Sort方法。然而在這裏,它正在排序的列表不是dataList,而是dataList.ToList(),這不是相同的項目。

因此,它將dataList.ToList()排序,但由於您沒有提及它,所以它會被丟棄,而您將留下未修改的dataList

最好的解決很可能會改變前行:

var dataList = data.ToList(); 

因此而不是檢查它是否是一個合適的IList等等,我們只是在做一個ToList(),以確保我們有一個列表所以下一行可以是:

dataList.Sort(new OrderComparer()); 

這將現在在正確的列表上工作,並希望從而做你想做的。

+1

感謝您的回答。你解決了我的問題 –

1

很難猜測是什麼問題,因爲你不提供後的實際結果樣本數據。

我想你應該更換

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

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

(不要忘記修改行numberY以及)。 由於字符串從索引0開始(並且您可能只抓取最後一位數字)。

雖然我會建議你簡單解析stringDateTime對象(有此一內置方法,這可能就足夠了),然後使用默認的可比性DateTime對象。這也會提高速度,因爲這種方法將解析string對象的平均O(n log n)次[而最壞情況O(n^2)次]而不是O(n)倍

+0

我們不知道字符串是DateTime,所以可能是愚蠢的。事實上,它是年,月和數字,而不是年/月/日,這表明它不是日期。我假設這個數字是一個自動遞增的數字,每個月都會重置一次。而第一部分是否正確完全是爲了讓OP知道。例如,它可以是像X10314這樣的代碼,其中X不需要進行排序。希望OP能回覆給我們關於他正在排序的數據的信息...... – Chris

+1

沒錯,只要TS沒有提供一些樣本數據,我們只能猜出真實的格式。儘管在這種情況下可以使用元組Tuple ,其中DataTime設置爲每個月的第一天。無論如何,它將簡化比較。 –