Tidak mengandung huruf besar-kecil

2909

Apakah ada cara untuk membuat pengembalian berikut ini benar?

string title = "ASTRINGTOTEST";
title.Contains("string");

Sepertinya tidak ada kelebihan yang memungkinkan saya untuk mengatur sensitivitas case .. Saat ini saya MENDUKUNG mereka berdua, tapi itu hanya konyol (yang saya maksudkan dengan masalah i18n yang datang dengan casing atas dan bawah).

PEMBARUAN
Pertanyaan ini sudah kuno dan sejak itu saya menyadari saya meminta jawaban sederhana untuk topik yang sangat luas dan sulit jika Anda ingin menyelidikinya sepenuhnya.
Untuk sebagian besar kasus, di mono-lingual, basis kode bahasa Inggris ini jawabannya akan cukup. Saya curiga karena kebanyakan orang yang datang ke sini termasuk dalam kategori ini, ini adalah jawaban yang paling populer. Namun jawaban
ini memunculkan masalah yang melekat bahwa kita tidak dapat membandingkan tidak peka huruf besar kecil sampai kita tahu kedua teks adalah budaya yang sama dan kita tahu apa budaya itu. Ini mungkin jawaban yang kurang populer, tetapi saya pikir itu lebih benar dan itulah sebabnya saya menandainya.

Boris Callens
sumber

Jawaban:

1398

Untuk menguji apakah string paragraphberisi string word(terima kasih @QuarterMeister)

culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0

Di mana culturecontoh CultureInfomenggambarkan bahasa tempat teks tersebut ditulis.

Solusi ini transparan tentang definisi tidak peka huruf besar-kecil, yang bergantung pada bahasa . Misalnya, bahasa Inggris menggunakan karakter Idan iuntuk versi huruf besar dan kecil dari huruf kesembilan, sedangkan bahasa Turki menggunakan karakter ini untuk huruf kesebelas dan kedua belas dari 29 huruf alfabet panjangnya. Versi huruf besar bahasa Turki dari 'i' adalah karakter asing 'İ'.

Jadi string tindan TINkata yang sama dalam bahasa Inggris , tetapi kata-kata yang berbeda dalam bahasa Turki . Seperti yang saya mengerti, yang satu berarti 'roh' dan yang lainnya adalah kata onomatopoeia. (Orang Turki, tolong koreksi saya jika saya salah, atau sarankan contoh yang lebih baik)

Sebagai rangkuman, Anda hanya bisa menjawab pertanyaan 'apakah kedua string ini sama tetapi dalam kasus yang berbeda' jika Anda tahu bahasa apa teks tersebut berada . Jika Anda tidak tahu, Anda harus mengambil tendangan. Mengingat hegemoni bahasa Inggris dalam perangkat lunak, Anda mungkin harus menggunakan CultureInfo.InvariantCulture, karena itu akan salah dengan cara yang akrab.

Kolonel Panic
sumber
67
Mengapa tidak culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0? Itu menggunakan budaya yang benar dan case-insensitive, itu tidak mengalokasikan string huruf kecil sementara, dan menghindari pertanyaan apakah mengkonversi ke huruf kecil dan membandingkan selalu sama dengan perbandingan case-insensitive.
Quartermeister
9
Solusi ini juga tidak perlu mencemari tumpukan dengan mengalokasikan memori untuk apa yang seharusnya menjadi fungsi pencarian
JaredPar
15
Membandingkan dengan ToLower () akan memberikan hasil yang berbeda dari Index-case-insensitive ketika dua huruf yang berbeda memiliki huruf kecil yang sama. Misalnya, memanggil ToLower () pada U + 0398 "Theta huruf kapital Yunani" atau U + 03F4 "Simbol Theta huruf kapital Yunani" menghasilkan U + 03B8, "Theta huruf kecil Yunani", tetapi huruf kapital dianggap berbeda. Kedua solusi menganggap huruf kecil dengan huruf kapital yang sama berbeda, seperti U + 0073 "Latin Small Letter S" dan U + 017F "Latin Small Letter Long S", sehingga solusi IndexOf tampaknya lebih konsisten.
Quartermeister
3
@ Quartermeister - dan BTW, saya percaya .NET 2 dan .NET4 berperilaku berbeda dalam hal ini. NET 4 selalu menggunakan NORM_LINGUISTIC_CASING sementara. NET 2 tidak (bendera ini muncul dengan Windows Vista).
Simon Mourier
10
Mengapa Anda tidak menulis "ddddfg" .IndexOf ("Df", StringComparison.OrdinalIgnoreCase)?
Chen
2713

Anda bisa menggunakan Metode String.IndexOf dan lulus StringComparison.OrdinalIgnoreCasesebagai jenis pencarian untuk digunakan:

string title = "STRING";
bool contains = title.IndexOf("string", StringComparison.OrdinalIgnoreCase) >= 0;

Yang lebih baik adalah mendefinisikan metode ekstensi baru untuk string:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source?.IndexOf(toCheck, comp) >= 0;
    }
}

Perhatikan, bahwa propagasi nol ?. tersedia sejak C # 6.0 (VS 2015), untuk penggunaan versi yang lebih lama

if (source == null) return false;
return source.IndexOf(toCheck, comp) >= 0;

PEMAKAIAN:

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);
JaredPar
sumber
3
Metode ekstensi string hebat! Saya telah mengedit milik saya untuk memeriksa string sumber bukan nol untuk mencegah kesalahan referensi objek terjadi saat melakukan .IndexOf ().
Richard Pursehouse
8
Ini memberikan jawaban yang sama paragraph.ToLower(culture).Contains(word.ToLower(culture))dengan CultureInfo.InvariantCulturedan tidak memecahkan masalah lokalisasi. Mengapa terlalu rumit? stackoverflow.com/a/15464440/284795
Kolonel Panic
60
@ ColonelPanic ToLowerversi ini menyertakan 2 alokasi yang tidak perlu dalam operasi perbandingan / pencarian. Mengapa tidak perlu mengalokasikan dalam skenario yang tidak memerlukannya?
JaredPar
4
@Seabiscuit yang tidak akan bekerja karena stringmerupakan IEnumerable<char>maka Anda tidak dapat menggunakannya untuk menemukan substring
JaredPar
6
Sebuah kata peringatan: Default untuk string.IndexOf(string)adalah dengan menggunakan budaya saat ini, sedangkan default untuk string.Contains(string)adalah dengan menggunakan pembanding ordinal. Seperti yang kita ketahui, yang pertama dapat diubah menjadi mengambil kelebihan yang lebih lama, sedangkan yang terakhir tidak dapat diubah. Konsekuensi dari ketidakkonsistenan ini adalah contoh kode berikut:Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; string self = "Waldstrasse"; string value = "straße"; Console.WriteLine(self.Contains(value));/* False */ Console.WriteLine(self.IndexOf(value) >= 0);/* True */
Jeppe Stig Nielsen
231

Anda bisa menggunakan IndexOf()seperti ini:

string title = "STRING";

if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
{
    // The string exists in the original
}

Karena 0 (nol) dapat berupa indeks, Anda mengecek terhadap -1.

MSDN

Posisi nilai indeks berbasis nol jika string itu ditemukan, atau -1 jika tidak. Jika nilainya String.Empty, nilai kembali adalah 0.

mkchandler
sumber
148

Solusi alternatif menggunakan Regex:

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);
Jed
sumber
6
Ide bagus, kami juga memiliki banyak kombinasi bitwise di RegexOptions seperti RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;bagi siapa saja jika membantu.
Saravanan
7
Harus mengatakan saya lebih suka metode ini walaupun menggunakan IsMatch untuk kerapian.
wonea
31
Yang lebih buruk, karena string pencarian ditafsirkan sebagai regex, sejumlah karakter tanda baca akan menyebabkan hasil yang salah (atau memicu pengecualian karena ekspresi yang tidak valid). Coba cari "."di "This is a sample string that doesn't contain the search string". Atau coba cari "(invalid", dalam hal ini.
cHao
17
@ cHao: Kalau begitu, Regex.Escapebisa membantu. Regex tampaknya masih tidak perlu ketika IndexOf/ ekstensi Containssederhana (dan bisa dibilang lebih jelas).
Dan Mangiarelli
6
Perhatikan bahwa saya tidak menyiratkan bahwa solusi Regex ini adalah cara terbaik untuk melakukannya. Saya hanya menambahkan ke daftar jawaban untuk pertanyaan yang diposting asli "Apakah ada cara untuk membuat pengembalian berikut ini benar?".
Jed
79

Anda selalu bisa menaikkan atau menurunkan string terlebih dahulu.

string title = "string":
title.ToUpper().Contains("STRING")  // returns true

Ups, lihat saja tadi. Perbandingan kasus yang sensitif *mungkin akan tetap *melakukan hal yang sama, dan jika kinerja tidak menjadi masalah, saya tidak melihat masalah dengan membuat salinan huruf besar dan membandingkannya. Saya bisa bersumpah bahwa saya pernah melihat membandingkan kasus-sensitif sekali ...

Ed S.
sumber
122
Cari "tes Turki" :)
Jon Skeet
7
Di beberapa lokal Prancis, huruf besar tidak memiliki diakritik, jadi ToUpper () mungkin tidak lebih baik dari ToLower (). Saya akan mengatakan menggunakan alat yang tepat jika tersedia - perbandingan case-insensitive.
Blair Conrad
5
Jangan gunakan ToUpper atau ToLower, dan lakukan apa yang dikatakan Jon Skeet
Peter Gfader
14
Hanya melihat ini lagi setelah dua tahun dan downvote baru ... lagi pula, saya setuju bahwa ada cara yang lebih baik untuk membandingkan string. Namun, tidak semua program akan dilokalkan (sebagian besar tidak akan) dan banyak yang merupakan aplikasi internal atau dibuang. Karena saya hampir tidak dapat mengharapkan pujian untuk saran yang terbaik untuk aplikasi sekali pakai ... Saya pindah: D
Ed S.
8
Apakah mencari "tes Turki" sama dengan mencari "TURKEY TEST"?
JackAce
55

Hanya .NET Core 2.0+ (mulai sekarang)

.NET Core telah memiliki sepasang metode untuk menangani hal ini sejak versi 2.0:

  • String.Contains (Char, StringComparison )
  • String.Contains (String, StringComparison )

Contoh:

"Test".Contains("test", System.StringComparison.CurrentCultureIgnoreCase);

Pada waktunya, mereka mungkin akan masuk ke dalam .NET Standard dan, dari sana, ke semua implementasi lain dari Base Class Library.

Mathieu Renda
sumber
1
Sekarang juga tersedia dalam .NET Standard 2.1
Paweł Bulwan
52

Salah satu masalah dengan jawabannya adalah bahwa ia akan mengeluarkan pengecualian jika string adalah nol. Anda dapat menambahkannya sebagai cek agar tidak:

public static bool Contains(this string source, string toCheck, StringComparison comp)
{
    if (string.IsNullOrEmpty(toCheck) || string.IsNullOrEmpty(source))
        return true;

    return source.IndexOf(toCheck, comp) >= 0;
} 
FeiBao 飞 豹
sumber
8
Jika toCheck adalah string kosong, ia harus mengembalikan true per dokumentasi Berisi: "true jika parameter nilai muncul dalam string ini, atau jika nilai adalah string kosong (" "); jika tidak, false."
amurra
3
Berdasarkan komentar amurra di atas, bukankah kode yang disarankan perlu diperbaiki? Dan bukankah ini harus ditambahkan ke jawaban yang diterima, sehingga jawaban terbaik adalah yang pertama?
David White
13
Sekarang ini akan mengembalikan true jika sumber adalah string kosong atau nol tidak peduli apa toCheck adalah. Itu tidak benar. Juga IndexOf sudah mengembalikan true jika toCheck adalah string kosong dan sumber tidak nol. Yang diperlukan di sini adalah cek untuk nol. Saya sarankan jika (sumber == null || nilai == null) kembali salah;
Colin
2
Sumber tidak boleh null
Lucas
1
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
Kyle Delaney
35

Kelas StringExtension adalah jalan maju, saya telah menggabungkan beberapa posting di atas untuk memberikan contoh kode lengkap:

public static class StringExtensions
{
    /// <summary>
    /// Allows case insensitive checks
    /// </summary>
    public static bool Contains(this string source, string toCheck, StringComparison comp)
    {
        return source.IndexOf(toCheck, comp) >= 0;
    }
}
Andrew
sumber
mengapa Anda membiarkan lapisan abstraksi LAINNYA berakhir StringComparison?
l --''''''--------- '' '' '' '' '' '' ''
35

Ini bersih dan sederhana.

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)
takirala
sumber
31
Ini akan cocok dengan suatu pola. Dalam contoh Anda, jika fileNamestrmemiliki karakter regex khusus (misalnya *, +, ., dll) maka Anda akan berada di untuk cukup mengejutkan. Satu-satunya cara untuk membuat solusi ini berfungsi seperti Containsfungsi yang tepat adalah melarikan diri fileNamestrdengan melakukan Regex.Escape(fileNamestr).
XåpplI'-I0llwlg'I -
selain itu, penguraian dan pencocokan regex jauh lebih banyak sumber daya daripada perbandingan kasus-sensitif sederhana
phuclv
29

OrdinalIgnoreCase, CurrentCultureIgnoreCase, atau InvariantCultureIgnoreCase?

Karena ini tidak ada, berikut adalah beberapa rekomendasi tentang kapan harus menggunakan yang mana:

Dos

  • Menggunakan StringComparison.OrdinalIgnoreCase untuk perbandingan sebagai standar aman Anda untuk pencocokan string agnostik kultur.
  • Gunakan StringComparison.OrdinalIgnoreCaseperbandingan untuk meningkatkan kecepatan.
  • Gunakan StringComparison.CurrentCulture-basedoperasi string saat menampilkan output ke pengguna.
  • Beralih penggunaan operasi string saat ini berdasarkan pada budaya invarian untuk menggunakan non-linguistik StringComparison.Ordinalatau StringComparison.OrdinalIgnoreCaseketika perbandingan secara
    linguistik tidak relevan (simbolis, misalnya).
  • Gunakan ToUpperInvariantdaripada ToLowerInvariantsaat menormalisasi string untuk perbandingan.

Larangan

  • Gunakan kelebihan beban untuk operasi string yang tidak secara eksplisit atau implisit menentukan mekanisme perbandingan string.
  • Gunakan operasi StringComparison.InvariantCulturestring berbasis-
    dalam banyak kasus; salah satu dari sedikit pengecualian adalah data yang secara
    linguistik bermakna tetapi agnostik secara budaya.

Berdasarkan aturan ini, Anda harus menggunakan:

string title = "STRING";
if (title.IndexOf("string", 0, StringComparison.[YourDecision]) != -1)
{
    // The string exists in the original
}

sedangkan [YourDecision] tergantung pada rekomendasi dari atas.

tautan sumber: http://msdn.microsoft.com/en-us/library/ms973919.aspx

Fabian Bigler
sumber
bagaimana jika Anda tahu Anda akan selalu mendapatkan string bahasa Inggris. yang mana yang akan digunakan?
BKSpurgeon
1
@ BKSpurgeon Saya akan menggunakan OrdinalIgnoreCase, jika kasing tidak masalah
Fabian Bigler
20

Ini adalah solusi termudah.

  1. Menurut Indeks

    string title = "STRING";
    
    if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
    {
        // contains 
    }
  2. Dengan Mengubah kasing

    string title = "STRING";
    
    bool contains = title.ToLower().Contains("string")
  3. Oleh Regex

    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
LAV VISHWAKARMA
sumber
11

Saya tahu bahwa ini bukan C #, tetapi dalam kerangka kerja (VB.NET) sudah ada fungsi seperti itu

Dim str As String = "UPPERlower"
Dim b As Boolean = InStr(str, "UpperLower")

Varian C #:

string myString = "Hello World";
bool contains = Microsoft.VisualBasic.Strings.InStr(myString, "world");
serio
sumber
11

The InStrMetode dari VisualBasic perakitan adalah yang terbaik jika Anda memiliki kekhawatiran tentang internasionalisasi (atau Anda bisa reimplement itu). Melihat di dalamnya dotNeetPeek menunjukkan bahwa itu tidak hanya memperhitungkan huruf besar dan kecil, tetapi juga untuk jenis kana dan karakter setengah-lebar-penuh (sebagian besar relevan untuk bahasa Asia, meskipun ada versi lebar-lebar dari alfabet Romawi juga ). Saya melewatkan beberapa detail, tetapi periksa metode pribadi InternalInStrText:

private static int InternalInStrText(int lStartPos, string sSrc, string sFind)
{
  int num = sSrc == null ? 0 : sSrc.Length;
  if (lStartPos > num || num == 0)
    return -1;
  if (sFind == null || sFind.Length == 0)
    return lStartPos;
  else
    return Utils.GetCultureInfo().CompareInfo.IndexOf(sSrc, sFind, lStartPos, CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth);
}
Casey
sumber
11

Seperti ini:

string s="AbcdEf";
if(s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}
cdytoby
sumber
3
Ini tidak spesifik untuk budaya dan mungkin gagal untuk beberapa kasus. culture.CompareInfo.IndexOf (paragraf, kata, CompareOptions.IgnoreCase) harus digunakan.
hikalkan
8

Gunakan ini:

string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);
mr.martan
sumber
26
Penanya mencari Containstidak Compare.
DuckMaestro
@DuckMaestro, jawaban yang diterima diterapkan Containsdengan IndexOf. Jadi pendekatan ini sama-sama membantu! Contoh kode C # pada halaman ini menggunakan string.Compare (). Pilihan tim SharePoint yaitu!
gagak vulcan
6

Ini sangat mirip dengan contoh lain di sini, tetapi saya telah memutuskan untuk menyederhanakan enum menjadi bool, primer karena alternatif lain biasanya tidak diperlukan. Ini contoh saya:

public static class StringExtensions
{
    public static bool Contains(this string source, string toCheck, bool bCaseInsensitive )
    {
        return source.IndexOf(toCheck, bCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal) >= 0;
    }
}

Dan penggunaannya adalah seperti:

if( "main String substring".Contains("SUBSTRING", true) )
....
TarmoPikaro
sumber
6

Menggunakan RegEx adalah cara langsung untuk melakukan ini:

Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);
Tetap
sumber
4
Jawaban Anda persis sama dengan guptat59, tetapi, seperti yang ditunjukkan pada jawabannya, ini akan cocok dengan ekspresi reguler, jadi jika string yang Anda uji mengandung karakter regex khusus, itu tidak akan menghasilkan hasil yang diinginkan.
Casey
2
Ini adalah salinan langsung dari jawaban ini dan menderita masalah yang sama seperti yang disebutkan dalam jawaban itu
Liam
Sepakat. Pelajari ungkapan reguler
Jared
5

Hanya untuk membangun jawaban di sini, Anda dapat membuat metode ekstensi string untuk membuatnya sedikit lebih ramah pengguna:

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }
Pengembang Melbourne
sumber
1
Anggap paragraf dan kata Anda akan selalu ada di AS
Boris Callens
3
Untuk menghindari masalah dengan memaksa budaya masuk ke AS, gunakan return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;saja.
AndrewWhalan
3

jika Anda ingin memeriksa apakah string yang Anda kirimkan dalam string maka ada metode sederhana untuk itu.

string yourStringForCheck= "abc";
string stringInWhichWeCheck= "Test abc abc";

bool isContained = stringInWhichWeCheck.ToLower().IndexOf(yourStringForCheck.ToLower()) > -1;

Nilai boolean ini akan kembali jika string berisi atau tidak

shaishav shukla
sumber
3

Sederhana dan berfungsi

title.ToLower().Contains("String".ToLower())
Pradeep Asanka
sumber
2
if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}
Tamilselvan K
sumber
2

Anda dapat menggunakan string.indexof ()fungsi. Ini akan menjadi case-sensitive

Okan SARICA
sumber
2

Kuncinya di sini adalah untuk mencari string, mengabaikan case, tetapi untuk tetap persis sama (dengan case yang sama).

 var s="Factory Reset";
 var txt="reset";
 int first = s.IndexOf(txt, StringComparison.InvariantCultureIgnoreCase) + txt.Length;
 var subString = s.Substring(first - txt.Length, txt.Length);

Output adalah "Reset"

Mr.B
sumber
-1
public static class StringExtension
{
    #region Public Methods

    public static bool ExContains(this string fullText, string value)
    {
        return ExIndexOf(fullText, value) > -1;
    }

    public static bool ExEquals(this string text, string textToCompare)
    {
        return text.Equals(textToCompare, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExHasAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index]) == false) return false;
        return true;
    }

    public static bool ExHasEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return true;
        return false;
    }

    public static bool ExHasNoEquals(this string text, params string[] textArgs)
    {
        return ExHasEquals(text, textArgs) == false;
    }

    public static bool ExHasNotAllEquals(this string text, params string[] textArgs)
    {
        for (int index = 0; index < textArgs.Length; index++)
            if (ExEquals(text, textArgs[index])) return false;
        return true;
    }

    /// <summary>
    /// Reports the zero-based index of the first occurrence of the specified string
    /// in the current System.String object using StringComparison.InvariantCultureIgnoreCase.
    /// A parameter specifies the type of search to use for the specified string.
    /// </summary>
    /// <param name="fullText">
    /// The string to search inside.
    /// </param>
    /// <param name="value">
    /// The string to seek.
    /// </param>
    /// <returns>
    /// The index position of the value parameter if that string is found, or -1 if it
    /// is not. If value is System.String.Empty, the return value is 0.
    /// </returns>
    /// <exception cref="ArgumentNullException">
    /// fullText or value is null.
    /// </exception>
    public static int ExIndexOf(this string fullText, string value)
    {
        return fullText.IndexOf(value, StringComparison.OrdinalIgnoreCase);
    }

    public static bool ExNotEquals(this string text, string textToCompare)
    {
        return ExEquals(text, textToCompare) == false;
    }

    #endregion Public Methods
}
Surga Terakhir
sumber
-4

Cara sederhana untuk pemula:

title.ToLower().Contains("string");//of course "string" is lowercase.
O Thạnh Ldt
sumber
Downvote hanya karena salah. Bagaimana jika title = StRiNg? StRiNg! = String dan StRiNg! = STRING
berniefitz
Saya salah. Edit jawaban sebagai berikut, terlalu sederhana sederhana: <br/> title.ToLower (). Berisi ("string") // tentu saja "string" adalah huruf kecil
O Thạnh Ldt