2011-03-16 115 views
2

我有這樣的LINQ查詢:LINQ和大小寫

TempRecordList = new ArrayList(TempRecordList.Cast<string>().OrderBy(s => s.Substring(9, 30)).ToArray()); 

它的偉大工程,在某種程度上這是正確的,但是從我想要的東西有點不同的執行排序。在查詢的結果我看到這樣的事情:

棕櫚Bouter,彼得
帕爾默 - 約翰遜,肖恩

而我真正需要的是有排序像這樣的名字:

帕爾默 - 約翰遜,肖恩
棕櫚Bouter,彼得

基本上我想要的「 - 」字符被視爲是較低的塔ñ字符,以便包含它的名稱稍後以上升搜索顯示。

這是另一個例子。我得到:

迪亞斯,雷金納德
DiBlackley,安東

相反的:

DiBlackley,安東
迪亞斯,雷金納德

正如你所看到的,同樣,由於如何處理大寫字母'B',訂單被切換。

所以我的問題是,我需要改變我的LINQ查詢,使它返回我指定的順序的結果。任何反饋將大大appreaciated。

順便說一句,我嘗試使用s.Substring(9,30).ToLower()但這並沒有幫助。

謝謝!

回答

6

要自定義排序順序,你需要創建一個實現IComparer<string>接口比較器類。 OrderBy()方法將比較器作爲第二個參數。

internal sealed class NameComparer : IComparer<string> { 
    private static readonly NameComparer DefaultInstance = new NameComparer(); 

    static NameComparer() { } 
    private NameComparer() { } 

    public static NameComparer Default { 
     get { return DefaultInstance; } 
    } 

    public int Compare(string x, string y) { 
     int length = Math.Min(x.Length, y.Length); 
     for (int i = 0; i < length; ++i) { 
      if (x[i] == y[i]) continue; 
      if (x[i] == '-') return 1; 
      if (y[i] == '-') return -1; 
      return x[i].CompareTo(y[i]); 
     } 

     return x.Length - y.Length; 
    } 
} 

這與下面的測試情況下至少工作:

var names = new[] { 
    "Palmer-Johnson, Sean", 
    "Palm-Bouter, Peter", 
    "Dias, Reginald", 
    "DiBlackley, Anton", 
}; 

var sorted = names.OrderBy(name => name, NameComparer.Default).ToList(); 

// sorted: 
// [0]: "DiBlackley, Anton" 
// [1]: "Dias, Reginald" 
// [2]: "Palmer-Johnson, Sean" 
// [3]: "Palm-Bouter, Peter" 
+0

聽起來好像它可能會工作,但我不確定我能寫一個能夠自己執行這些比較的類。 – GonzoKnight 2011-03-16 17:04:30

+0

@mgronber - 非常感謝!我會嘗試這個代碼並返回結果。 – GonzoKnight 2011-03-16 17:36:20

+0

我似乎有一個問題,以下行:[b]內部密封類NameComparer:IComparer [b]。我得到:錯誤1非泛型類型'System.Collections.IComparer'不能與類型參數一起使用。我可能知道如何解決它。我會嘗試別的,並會回來。 – GonzoKnight 2011-03-16 17:54:49

0

OrderBy()返回結果中的升序。

eh之前,因此第一個結果(請記住,你要比較的是,在第9個位置的字符...不是字符串的開頭啓動子)和iy之前,因此第二。區分大小寫與它無關。

如果你想按降序排列的結果,你應該使用OrderByDescending()

TempRecordList.Cast<string> 
       .OrderByDescending(s => s.Substring(9, 30)).ToArray()); 
+0

但我真的希望結果以ASCENDING順序返回。我的問題可能沒有說清楚,但所有的結果都相對於對方排列良好。只是上面的名字不符合我的要求。我想,我真正想做的是改變升序排序的方式。有沒有文化或我可以指定的東西?謝謝! – GonzoKnight 2011-03-16 17:02:46

+0

@GonzoKnight - 我想我錯過了你想要完成的事情。您正在根據原始字符串(正在正確完成)的子字符串進行挖掘,但您不希望以這種方式顯示它們。如果是這樣的話,那麼爲什麼要根據子字符串對它們進行排序呢? – 2011-03-16 17:04:20

+0

不要讓這部分混淆你。整個項目是Cobol到C#的轉換,顯然Cobol中的升序規則有點不同。我剛纔提到的首選順序來自Cobol輸出。我的結果是99.5%正確,但2200中有15個名稱排序錯誤。我上面給出的例子幾乎涵蓋了兩個輸出不兼容的範圍。所以我顯示結果,我只是想讓它們完全相同。 – GonzoKnight 2011-03-16 17:08:29

0

你可能只想實現一個自定義的IComparer對象,這將使自定義優先特殊,大寫和小寫字符。

http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx

+0

我試過這樣做,實際上。這是我想出來的:public class ArrayComparer:IComparer {public int Compare(object x,object y){string left = x.ToString(); string right = y.ToString(); string lhs = left.Substring(9,30); string rhs = right.Substring(9,30);返回lhs.CompareTo(rhs); }}但這只是定期比較。我不知道如何改變它,以便爲特殊,大寫和小寫字符提供自定義優先級。 – GonzoKnight 2011-03-16 17:13:20

2

如已經提到的,OrderBy()方法以一個比較器作爲第二參數。

對於字符串,您不一定非得實施IComparer<string>。您可能會在System.StringComparer.CurrentCulture(或System.StringComparer中的其他人之一)下行。

然而,在你的確切情況下,沒有內置的比較器,它將處理排序順序後的-