5

ソートされた文字列の配列があります。接頭辞を識別する文字列が与えられた場合、2 つのバイナリ検索を実行して、その接頭辞で始まる単語を含む配列内の最初と最後の位置を見つけます。

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

つまり、2 つの文字列は等しいと見なされます。コードを変更すると

int lastPosition = Array.BinarySearch<string>(words, prefix + "z");

正しい答えが得られます。さらに、私はそれを発見しました

("abc"+char.MaxValue)==("abc")

正しく(私のニーズに関して)falseを返します。

CompareTo メソッドの動作を説明していただけませんか?

BinarySearch メソッドが lastPosition に対して 3 を返すように、CompareTo メソッドを == のように動作させたいと考えています。

4

2 に答える 2

6

string.CompareTo()current-culture 比較を行います。内部的には を使用し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
于 2012-11-20T11:15:00.597 に答える
5

MSDN によると、string.CompareTo2 つの文字列が等しいかどうかを確認するために使用しないでください。

CompareTo メソッドは、主に並べ替えまたはアルファベット順の操作で使用するために設計されました。メソッド呼び出しの主な目的が 2 つの文字列が等しいかどうかを判断することである場合は、使用しないでください。2 つの文字列が等しいかどうかを判断するには、Equals メソッドを呼び出します。

希望する動作を得るには、次を受け入れるオーバーロードを利用できますIComparer<T>

int lastPosition = Array.BinarySearch<string>(words, prefix + char.MaxValue, 
                                              StringComparer.Ordinal);

配列にその接頭辞を持つ文字列がないため、これは-4forを返します。lastPositionその場合、なぜあなたが期待するのか理解できません3...

于 2012-11-20T11:10:58.470 に答える