Bagikan melalui


Cara membandingkan string di C #

Anda membandingkan string untuk menjawab salah satu dari dua pertanyaan: "Apakah kedua string ini sama?" atau "Dalam urutan apa string ini harus ditempatkan saat mengurutkannya?"

Kedua pertanyaan itu diperumit oleh faktor-faktor yang mempengaruhi perbandingan string:

  • Anda dapat memilih perbandingan ordinal atau linguistik.
  • Anda dapat memilih apakah kasus penting.
  • Anda dapat memilih perbandingan khusus budaya.
  • Perbandingan linguistik tergantung pada budaya dan platform.

Bidang System.StringComparison enumerasi mewakili pilihan ini:

  • CurrentCulture: Bandingkan string menggunakan aturan pengurutan sensitif budaya dan budaya saat ini.
  • CurrentCultureIgnoreCase: Bandingkan string menggunakan aturan pengurutan sensitif budaya, budaya saat ini, dan mengabaikan kasus string yang dibandingkan.
  • InvariantCulture: Bandingkan string menggunakan aturan pengurutan sensitif budaya dan budaya invarian.
  • InvariantCultureIgnoreCase: Bandingkan string menggunakan aturan pengurutan sensitif budaya, budaya invarian, dan mengabaikan kasus string yang dibandingkan.
  • Ordinal: Bandingkan string menggunakan aturan pengurutan ordinal (biner).
  • OrdinalIgnoreCase: Bandingkan string menggunakan aturan pengurutan ordinal (biner) dan mengabaikan kasus string yang dibandingkan.

Catatan

Contoh C# dalam artikel ini dijalankan di Try.NET pelari kode sebaris dan taman bermain. Pilih tombol Jalankan untuk menjalankan contoh di jendela interaktif. Setelah Anda menjalankan kode, Anda dapat memodifikasinya dan menjalankan kode yang dimodifikasi dengan memilih Jalankan lagi. Kode yang dimodifikasi berjalan di jendela interaktif atau, jika kompilasi gagal, jendela interaktif menampilkan semua pesan kesalahan pengompilasi C#.

Ketika Anda membandingkan string, Anda menentukan urutan di antara mereka. Perbandingan digunakan untuk mengurutkan urutan string. Setelah urutannya dalam urutan yang diketahui, lebih mudah untuk mencari, baik untuk perangkat lunak maupun untuk manusia. Perbandingan lain mungkin memeriksa apakah string sama. Pemeriksaan kesamaan ini mirip dengan kesetaraan, tetapi beberapa perbedaan, seperti perbedaan kasus, mungkin diabaikan.

Perbandingan ordinal default

Secara default, operasi yang paling umum:

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")}");

Perbandingan ordinal default tidak memperhitungkan aturan linguistik saat membandingkan string. Ini membandingkan nilai biner setiap objek Char dalam dua string. Akibatnya, perbandingan ordinal default juga peka huruf besar/kecil.

Pengujian untuk kesetaraan dengan String.Equals dan == dan operator != berbeda dari perbandingan string menggunakan metode String.CompareTo dan Compare(String, String). Semuanya melakukan perbandingan peka huruf besar/kecil. Namun, sementara tes untuk kesetaraan melakukan perbandingan ordinal, metode CompareTo dan Compare melakukan perbandingan linguistik sadar budaya menggunakan budaya saat ini. Buat niat kode Anda jelas dengan memanggil kelebihan beban yang secara eksplisit menentukan jenis perbandingan yang akan dilakukan.

Perbandingan ordinal yang tidak peka huruf besar/kecil

Metode String.Equals(String, StringComparison) memungkinkan Anda menentukan nilai StringComparison dari StringComparison.OrdinalIgnoreCase untuk perbandingan ordinal yang tidak peka huruf besar/kecil. Ada juga metode statis String.Compare(String, String, StringComparison) yang melakukan perbandingan ordinal yang tidak peka huruf besar/kecil jika Anda menentukan nilai StringComparison.OrdinalIgnoreCase untuk StringComparison argumen. Perbandingan ini ditampilkan dalam kode berikut:

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");

Metode ini menggunakan konvensi casing dari budaya invarian saat melakukan perbandingan ordinal yang tidak peka huruf besar/kecil.

Perbandingan linguistik

Banyak metode perbandingan string (seperti String.StartsWith) menggunakan aturan linguistik untuk budaya saat ini secara default untuk memesan input mereka. Perbandingan linguistik ini terkadang disebut sebagai "urutan pengurutan kata." Ketika Anda melakukan perbandingan linguistik, beberapa karakter Unicode non-phanumeric mungkin memiliki bobot khusus yang ditetapkan. Misalnya, tanda hubung "-" mungkin memiliki bobot kecil yang ditetapkan untuk itu sehingga "co-op" dan "coop" muncul di samping satu sama lain dalam urutan sortir. Beberapa karakter kontrol noncetak mungkin diabaikan. Selain itu, beberapa karakter Unicode mungkin setara dengan urutan Char instans. Contoh berikut menggunakan frasa "Mereka menari di jalan." dalam bahasa Jerman dengan "ss" (U+0073 U+0073) dalam satu string dan 'ß' (U+00DF) di string lainnya. Secara linguistik (dalam Windows), "ss" sama dengan karakter Esszet: 'ß' Jerman dalam kedua budaya "en-US" dan "de-DE".

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");
}

Pada Windows, sebelum .NET 5, urutan sortir perubahan "cop", "coop", dan "co-op" ketika Anda berubah dari perbandingan linguistik dengan perbandingan ordinal. Kedua kalimat Jerman juga membandingkan secara berbeda menggunakan jenis perbandingan yang berbeda. Sebelum .NET 5, API globalisasi .NET menggunakan pustaka Dukungan Bahasa Nasional (NLS ). Dalam .NET 5 dan versi yang lebih baru, API globalisasi .NET menggunakan pustaka Komponen Internasional untuk Unicode (ICU), yang menyatukan perilaku globalisasi NET di semua sistem operasi yang didukung.

Perbandingan menggunakan budaya tertentu

Contoh berikut menyimpan CultureInfo objek untuk budaya en-US dan de-DE. Perbandingan dilakukan menggunakan objek CultureInfo untuk memastikan perbandingan khusus budaya. Budaya yang digunakan mempengaruhi perbandingan linguistik. Contoh berikut menunjukkan hasil membandingkan dua kalimat Jerman menggunakan budaya "en-US" dan budaya "de-DE":

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");
}

Perbandingan yang peka terhadap budaya biasanya digunakan untuk membandingkan dan mengurutkan input string oleh pengguna dengan input string lain oleh pengguna. Karakter dan konvensi penyortiran string ini mungkin bervariasi tergantung pada lokal komputer pengguna. Bahkan string yang berisi karakter identik mungkin mengurutkan secara berbeda tergantung pada budaya utas saat ini.

Pemilahan linguistik dan string pencarian dalam array

Contoh berikut menunjukkan cara mengurutkan dan mencari string dalam array menggunakan perbandingan linguistik tergantung pada budaya saat ini. Anda menggunakan metode statis Array yang mengambil parameter System.StringComparer.

Contoh berikut menunjukkan cara mengurutkan array string menggunakan budaya saat ini:

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}");
}

Setelah array diurutkan, Anda dapat mencari entri menggunakan pencarian biner. Pencarian biner dimulai di tengah koleksi untuk menentukan setengah dari koleksi mana yang akan berisi string yang dicari. Setiap perbandingan berikutnya membagi bagian yang tersisa dari koleksi menjadi dua. Array diurutkan menggunakan StringComparer.CurrentCulture. Fungsi lokal ShowWhere menampilkan informasi tentang di mana string ditemukan. Jika string tidak ditemukan, nilai yang dikembalikan menunjukkan di mana itu akan terjadi jika ditemukan.

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}.");
    }
}

Penyortiran dan pencarian Ordinal dalam koleksi

Kode berikut menggunakan kelas koleksi System.Collections.Generic.List<T> untuk menyimpan string. String diurutkan menggunakan metode List<T>.Sort. Metode ini membutuhkan delegasi yang membandingkan dan memesan dua string. Metode String.CompareTo menyediakan fungsi perbandingan tersebut. Jalankan sampel dan amati urutannya. Operasi pengurutan ini menggunakan pengurutan ordinal yang peka huruf besar/kecil. Anda akan menggunakan metode statis String.Compare untuk menentukan aturan perbandingan yang berbeda.

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}");
}

Setelah diurutkan, daftar string dapat dicari menggunakan pencarian biner. Sampel berikut menunjukkan cara mencari daftar yang diurutkan menggunakan fungsi perbandingan yang sama. Fungsi lokal ShowWhere menunjukkan letak teks yang dicari adalah atau akan:

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}.");
    }
}

Selalu pastikan untuk menggunakan jenis perbandingan yang sama untuk menyortir dan mencari. Menggunakan jenis perbandingan yang berbeda untuk menyortir dan mencari menghasilkan hasil yang tidak terduga.

Kelas koleksi seperti System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey,TValue>, dan System.Collections.Generic.List<T> memiliki konstruktor yang mengambil parameter System.StringComparer ketika jenis elemen atau kunci adalah string. Secara umum, Anda harus menggunakan konstruktor ini jika memungkinkan, dan menentukan StringComparer.Ordinal atau StringComparer.OrdinalIgnoreCase.

Lihat juga