Megosztás a következőn keresztül:


Sztringek összehasonlítása a C-ben#

A sztringeket két kérdés egyikének megválaszolásához hasonlítja össze: "Egyenlő ez a két sztring?" vagy "Milyen sorrendben kell elhelyezni ezeket a sztringeket a rendezés során?"

Ezt a két kérdést a sztringek összehasonlítását befolyásoló tényezők bonyolítják:

  • Választhat egy sorszám- vagy nyelvi összehasonlítást.
  • Kiválaszthatja, hogy az eset számít-e.
  • Választhat kultúraspecifikus összehasonlításokat.
  • A nyelvi összehasonlítások kultúrától és platformfüggők.

Az System.StringComparison enumerálási mezők a következő lehetőségeket jelölik:

  • CurrentCulture: A sztringek összehasonlítása a kultúraérzékeny rendezési szabályok és az aktuális kultúra használatával.
  • CurrentCultureIgnoreCase: A sztringek összehasonlítása kulturális szempontból érzékeny rendezési szabályokkal, az aktuális kultúrával és az összehasonlítandó sztringek esetének figyelmen kívül hagyásával.
  • InvariantCulture: Hasonlítsa össze a sztringeket a kultúraérzékeny rendezési szabályok és az invariáns kultúra használatával.
  • InvariantCultureIgnoreCase: Hasonlítsa össze a sztringeket a kultúraérzékeny rendezési szabályok, az invariáns kultúra és az összehasonlítandó sztringek esetének figyelmen kívül hagyásával.
  • Sorszám: Sztringek összehasonlítása sorszámos (bináris) rendezési szabályok használatával.
  • OrdinalIgnoreCase: Hasonlítsa össze a sztringeket sorszámos (bináris) rendezési szabályokkal, és figyelmen kívül hagyja az összehasonlítandó sztringek esetét.

Feljegyzés

A cikkben szereplő C#-példák a Try.NET beágyazott kódfuttatóban és játszótéren futnak. Kattintson a Futtatás gombra egy példa interaktív ablakban való futtatásához. Miután végrehajtotta a kódot, módosíthatja és futtathatja a módosított kódot a Futtatás gombra kattintva. A módosított kód vagy az interaktív ablakban fut, vagy ha a fordítás sikertelen, az interaktív ablakban megjelenik az összes C#-fordító hibaüzenet.

A sztringek összehasonlításakor egy sorrendet határoz meg közöttük. Az összehasonlítások sztringek sorozatának rendezésére szolgálnak. Ha a sorozat ismert sorrendben van, könnyebben kereshető mind a szoftverek, mind az emberek számára. Más összehasonlítások is ellenőrizhetik, hogy a sztringek megegyeznek-e. Ezek az azonossági ellenőrzések hasonlóak az egyenlőséghez, de bizonyos eltéréseket, például a kis- és nagybetűket figyelmen kívül lehet hagyni.

Alapértelmezett sorszám-összehasonlítások

Alapértelmezés szerint a leggyakoribb műveletek:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

result = root.Equals(root2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}");

Az alapértelmezett sorszám-összehasonlítás nem veszi figyelembe a nyelvi szabályokat a sztringek összehasonlításakor. Két sztringben hasonlítja össze az egyes Char objektumok bináris értékét. Ennek eredményeképpen az alapértelmezett sorszám-összehasonlítás a kis- és nagybetűk megkülönböztetése is.

Az egyenlőség String.Equals és az ==!= operátorok tesztelése eltér a sztringek összehasonlításától a metódusok és Compare(String, String) a String.CompareTo metódusok használatával. Mindegyik megkülönbözteti a kis- és nagybetűk összehasonlítását. Míg azonban az egyenlőségi tesztek pontos összehasonlítást végeznek, a módszerek és Compare a CompareTo módszerek a kultúratudatos nyelvi összehasonlítást hajtanak végre a jelenlegi kultúrával. A kód szándékának egyértelművé tétele egy túlterhelés meghívásával, amely explicit módon meghatározza a végrehajtandó összehasonlítás típusát.

Kis- és nagybetűk érzéketlen összehasonlítása

A String.Equals(String, StringComparison) módszer lehetővé teszi a StringComparison kis- és nagybetűk érzéketlen összehasonlítása értékének StringComparison.OrdinalIgnoreCase megadását. Van egy statikus String.Compare(String, String, StringComparison) módszer is, amely kis- és nagybetűk érzéketlen sorszámának összehasonlítását hajtja végre, ha az StringComparison argumentum értékét StringComparison.OrdinalIgnoreCase adja meg. Ezek az összehasonlítások a következő kódban jelennek meg:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase);
int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase);

Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}");
if (comparison < 0)
    Console.WriteLine($"<{root}> is less than <{root2}>");
else if (comparison > 0)
    Console.WriteLine($"<{root}> is greater than <{root2}>");
else
    Console.WriteLine($"<{root}> and <{root2}> are equivalent in order");

Ezek a módszerek az invariáns kultúra casing konvencióit használják a kis- és nagybetűk érzéketlen összehasonlítása során.

Nyelvi összehasonlítások

Számos sztring-összehasonlító módszer (például String.StartsWith) alapértelmezés szerint nyelvi szabályokat használ a jelenlegi kultúrához a bemenetek sorrendjéhez. Ezt a nyelvi összehasonlítást néha "szórendezésnek" is nevezik. Ha nyelvi összehasonlítást végez, előfordulhat, hogy egyes nonalphanumerikus Unicode-karakterekhez speciális súlyok vannak hozzárendelve. A "-" kötőjel például kis súlyú lehet ahhoz, hogy a "kooperatív" és a "coop" rendezési sorrendben jelenjen meg egymás mellett. Egyes nem nyomtatható vezérlőkarakterek figyelmen kívül hagyhatók. Emellett egyes Unicode-karakterek egyenértékűek lehetnek a példányok sorozatával Char . Az alábbi példa a "Táncolnak az utcán" kifejezést használja németül az "ss" (U+0073 U+0073) sztringben, a "ß" (U+00DF) pedig egy másikban. Nyelvileg (Windowsban) az "ss" egyenlő a német Esszettel: "ß" karakter mind az "en-US" és a "de-DE" kultúrákban.

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

bool equal = String.Equals(first, second, StringComparison.InvariantCulture);
Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal.");
showComparison(first, second);

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words);
showComparison(word, other);
showComparison(words, other);
void showComparison(string one, string two)
{
    int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using invariant culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

Windows rendszeren a .NET 5 előtt a "cop", a "coop" és a "co-op" rendezési sorrendje megváltozik, amikor nyelvi összehasonlításról sorrendi összehasonlításra vált. A két német mondat a különböző összehasonlítási típusok használatával is eltérően hasonlít. A .NET 5 előtt a .NET globalizációs API-k nemzeti nyelvi támogatási (NLS-) kódtárakat használtak. A .NET 5-ös és újabb verzióiban a .NET globalizációs API-k a Unicode (ICU) kódtárak nemzetközi összetevőit használják, amelyek egységesülnek. A NET globalizációs viselkedése az összes támogatott operációs rendszeren.

Adott kultúrákat használó összehasonlítások

Az alábbi példa az en-US és a de-DE kultúrák objektumait tárolja CultureInfo . Az összehasonlításokat objektum CultureInfo használatával hajtjuk végre a kultúraspecifikus összehasonlítás biztosítása érdekében. Az alkalmazott kultúra hatással van a nyelvi összehasonlításokra. Az alábbi példa a két német mondat "en-US" kultúrával és a "de-DE" kultúrával való összehasonlításának eredményeit mutatja be:

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

var en = new System.Globalization.CultureInfo("en-US");

// For culture-sensitive comparisons, use the String.Compare
// overload that takes a StringComparison value.
int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {en.Name} returns {i}.");

var de = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, de, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {de.Name} returns {i}.");

bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal.");

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words, en);
showComparison(word, other, en);
showComparison(words, other, en);
void showComparison(string one, string two, System.Globalization.CultureInfo culture)
{
    int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using en-US culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

A kulturális szempontból érzékeny összehasonlításokat általában a felhasználók által bevitt sztringek összehasonlítására és rendezésére használják, és a felhasználók más sztringeket használnak. A sztringek karakterei és rendezési konvenciók a felhasználó számítógépének területi beállításától függően változhatnak. Az azonos karaktereket tartalmazó sztringek is eltérően rendezhetők az aktuális szál kultúrájától függően.

Nyelvi rendezés és sztringek keresése tömbökben

Az alábbi példák bemutatják, hogyan rendezheti és kereshet sztringeket egy tömbben az aktuális kultúrától függő nyelvi összehasonlítással. A paramétert System.StringComparer használó statikus Array metódusokat használja.

Az alábbi példa bemutatja, hogyan rendezhet egy sztringtömböt az aktuális kultúra használatával:

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

// Specify Ordinal to demonstrate the different behavior.
Array.Sort(lines, StringComparer.CurrentCulture);

foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

A tömb rendezése után bináris kereséssel kereshet bejegyzéseket. A gyűjtemény közepén elindul egy bináris keresés, amely meghatározza, hogy a gyűjtemény melyik fele tartalmazná a keresett sztringet. Minden további összehasonlítás felére bontja a gyűjtemény fennmaradó részét. A tömb rendezése a StringComparer.CurrentCulture. A helyi függvény ShowWhere információkat jelenít meg arról, hogy hol található a sztring. Ha a sztring nem található, a visszaadott érték azt jelzi, hogy hol lenne, ha megtalálná.

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
Array.Sort(lines, StringComparer.CurrentCulture);

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(T[] array, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{array[index - 1]} and ");

        if (index == array.Length)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{array[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

Rendezés és keresés a gyűjteményekben

Az alábbi kód a gyűjteményosztályt használja a System.Collections.Generic.List<T> sztringek tárolására. A sztringek rendezése a List<T>.Sort metódussal történik. Ehhez a metódushoz olyan meghatalmazottra van szükség, aki két sztringet hasonlít össze és rendel. A String.CompareTo metódus ezt az összehasonlító függvényt biztosítja. Futtassa a mintát, és figyelje meg a sorrendet. Ez a rendezési művelet a kis- és nagybetűkre érzékeny rendezést használja. A statikus String.Compare metódusok használatával különböző összehasonlító szabályokat adhat meg.

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

lines.Sort((left, right) => left.CompareTo(right));
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

A rendezés után a sztringek listája bináris kereséssel kereshető. Az alábbi minta bemutatja, hogyan kereshet a rendezett listában ugyanazzal az összehasonlító függvénnyel. A helyi függvény ShowWhere a keresett szöveg helyét jeleníti meg:

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
lines.Sort((left, right) => left.CompareTo(right));

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = lines.BinarySearch(searchString);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(IList<T> collection, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{collection[index - 1]} and ");

        if (index == collection.Count)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{collection[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

Mindig azonos típusú összehasonlítást használjon a rendezéshez és a kereséshez. Ha különböző összehasonlító típusokat használ a rendezéshez és a kereséshez, az váratlan eredményeket eredményez.

Az olyan gyűjteményosztályok, mint a System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey,TValue>és System.Collections.Generic.List<T> olyan konstruktorokkal rendelkeznek, amelyek paramétert System.StringComparer vesznek fel, ha az elemek vagy kulcsok típusa.string Általában ezeket a konstruktorokat kell használnia, amikor csak lehetséges, és adja meg vagy StringComparer.OrdinalStringComparer.OrdinalIgnoreCase.

Lásd még