我有自定义IComparer<string>
我用它来比较忽略其大小写的字符串和这样的符号:
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 :(得分:1)
这里有一个非常有趣的问题。 Internaly CompareInfo.Compare使用InternalCompareString
方法从COMNlsInfo::InternalCompareString
引入clr.dll
:
// 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
实现中重用它。
答案 1 :(得分:1)
可能没有这样的“输出字符串”。我会以这种方式实施您的Equals
:
return liberalStringComparer.Compare(x, y) == 0;
GetHashCode
更复杂。
一些方法:
return 0;
这样糟糕的实现(这意味着您必须始终运行Compare
才能知道它们是否相同。)由于您的比较相对简单(不变文化,序数忽略大小写比较),您应该能够创建通常有效的哈希。但是,如果没有对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
}
char.IsSymbol
true
所有位置,然后在其上使用StringComparer.InvariantCulture.GetHashCode
来形成字符串。 CompareInfo.GetSortKey
的哈希码应该是合适的值。
public int GetHashCode(string value)
{
return _compareInfo.GetSortKey(value, COMPARE_OPTIONS).GetHashCode();
}