我有一个排序的字符串数组。 给定一个标识前缀的字符串,我执行两次二进制搜索,找到数组中包含以该前缀开头的单词的第一个和最后一个位置:
string [] words = {"aaa","abc","abcd","acd"};
string prefix = "abc";
int firstPosition = Array.BinarySearch<string>(words, prefix);
int lastPosition = Array.BinarySearch<string>(words, prefix + char.MaxValue);
if (firstPosition < 0)
firstPosition = ~firstPosition;
if (lastPosition < 0)
lastPosition = ~lastPosition;
运行此代码我得到firstPosition和lastPosition都等于1,而正确的答案是让lastPosition等于3(即指向第一个不匹配的单词)。 BinarySearch方法使用CompareTo方法来比较对象,我发现了
("abc"+char.MaxValue).CompareTo("abc")==0
意味着两个字符串被认为是相等的! 如果我用
更改代码int lastPosition = Array.BinarySearch<string>(words, prefix + "z");
我得到了正确的答案。 而且我发现了
("abc"+char.MaxValue)==("abc")
正确(根据我的需要)返回false。
你能帮我解释一下CompareTo方法的行为吗?
我希望CompareTo方法的行为类似于==,以便BinarySearch方法为lastPosition返回3。
答案 0 :(得分:6)
string.CompareTo()
进行当前文化比较。在内部,它使用StringComparer.CurrentCulture
,而字符串equals-operator执行文化不变的比较。
例如,如果当前文化是“DE”,您将获得与“ss”和“ß”相同的结果:
Console.WriteLine("ss".CompareTo("ß")); // => 0
Console.WriteLine("ss" == "ß"); // => false
你想要的是一种文化不变的比较,你可以使用StringComparer.Ordinal
获得:
StringComparer.Ordinal.Compare("ss", "ß"); // => -108
StringComparer.Ordinal.Compare("abc"+char.MaxValue, "abc"); // => 65535
答案 1 :(得分:5)
根据MSDN,不应使用string.CompareTo
来检查两个字符串是否相等:
CompareTo方法主要用于排序或字母顺序操作。当方法调用的主要目的是确定两个字符串是否相等时,不应使用它。要确定两个字符串是否相等,请调用Equals方法。
要获得您希望的行为,您可以使用接受IComparer<T>
的重载:
int lastPosition = Array.BinarySearch<string>(words, prefix + char.MaxValue,
StringComparer.Ordinal);
这将为-4
返回lastPosition
,因为数组中没有包含该前缀的字符串。在这种情况下,我不明白为什么你期望3
...