2014-04-16 57 views
1

我已經定製IComparer<string>,我用比較字符串忽略他們的情況和符號這樣的:我可以獲得用於與CompareOptions比較的結果字符串嗎?

public class LiberalStringComparer : IComparer<string> 
    { 

     private readonly CompareInfo _compareInfo = CultureInfo.InvariantCulture.CompareInfo; 
     private const CompareOptions COMPARE_OPTIONS = CompareOptions.IgnoreSymbols | CompareOptions.OrdinalIgnoreCase; 


     public int Compare(string x, string y) 
     { 
      if (x == null) return -1; 
      if (y == null) return 1; 
      return this._compareInfo.Compare(x, y, COMPARE_OPTIONS); 
     } 
    } 

我能獲得輸出字符串是,最終用於比較?

我的最終目標是生產和IEqualityComparer<string>,它忽略符號和套管的方式與此比較器相同。

我可以編寫正則表達式來做到這一點,但不能保證我的正則表達式將使用與內置比較選項相同的邏輯。

+0

如果你有興趣,在短短'Equals'你可以做'yourComparer.Compare(X,Y)== 0' –

+0

@SriramSakthivel是的,但不符合的所有要求' IEqualityComparer' ...我仍然需要'GetHashCode' – Matthew

+0

是否有可能在比較它們之前,以某種方式*將字符串解析爲新的一致結構(或轉換爲一致的字符串類型)?它會使所有這些在概念上更簡單。 –

回答

1

可能沒有這樣的「輸出字符串」。我會實現你的Equals這樣:

return liberalStringComparer.Compare(x, y) == 0; 

GetHashCode更爲複雜。

一些方法:

  1. 使用執行不力像return 0;(這意味着你總是要運行Compare知道,如果他們是平等的)。
  2. 由於你的比較是相對簡單的(不變的文化,ordinal忽略大小寫比較),你應該能夠做出一般工作的散列。但是,如果不對Unicode和測試進行廣泛的研究,我不會建議您假設這將適用於任何文化的有效Unicode字符串的任何

    僞代碼:

    public int GetHashCode(string value) 
    { 
        // for each index in value 
        if (!char.IsSymbol(value, i)) 
         // add value[i].ToUpperInvariant() to the hash using an algorithm 
         // like http://stackoverflow.com/a/263416/781792 
    } 
    
  3. 形式;通過刪除所有地方char.IsSymboltrue,然後在其上使用StringComparer.InvariantCulture.GetHashCode
  4. CompareInfo.GetSortKey的散列碼應該是一個合適的值。

    public int GetHashCode(string value) 
    { 
        return _compareInfo.GetSortKey(value, COMPARE_OPTIONS).GetHashCode(); 
    } 
    
+0

我想我可以刪除所有返回true的字符'char.IsSymbol || char.IsWhiteSpace',然後對這些結果字符串執行'CultureInvariantIgnoreCase.GetHashCode' ...或者,我可以使用'GetUnicodeCategory'方法並明確排除類別。 – Matthew

+0

看來'char.IsSymbol'不會爲空白字符返回true。我認爲,相反,我想明確地包含那些屬於'char.IsLetterOrDigit' – Matthew

+0

我選擇了這個答案,因爲我必須創建自己的可靠的字符串處理器來刪除空格和符號,然後我使用了內置的CultureInvariantCaseInsensitive解決方案 – Matthew

1

這裏很有趣的問題。 Internaly CompareInfo.Compare使用InternalCompareString方法從clr.dll inporting COMNlsInfo::InternalCompareString

// Compare a string using the native API calls -- COMNlsInfo::InternalCompareString 
... 
private static extern int InternalCompareString(IntPtr handle, 
      IntPtr handleOrigin, String localeName, String string1, int offset1, 
      int length1, String string2, int offset2, int length2, int flags); 

換句話說,因爲你不能確定有關的內置函數的邏輯,也許你應該寫自己,並在這兩個IEqualityComparer重用和IComparer實現。

+0

+1用於證明我無法可靠地複製內置函數,並且應該使用自定義且明確定義的'IComparer '和'IEqualityComparer ' – Matthew

相關問題