Büyük / küçük harfe duyarlı olmayan 'İçerir (dize)'


2907

Aşağıdaki dönüşü gerçekleştirmenin bir yolu var mı?

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

Durum hassasiyetini ayarlamama izin veren bir aşırı yük var gibi görünmüyor .. Şu anda ikisini de ÜSTLÜYORUM, ama bu sadece aptalca ( yukarı ve aşağı kasa ile gelen i18n sorunlarına atıfta bulunuyorum ).

GÜNCELLEME
Bu soru eski ve o zamandan beri, tam olarak araştırmayı önemsiyorsanız gerçekten çok geniş ve zor bir konu için basit bir cevap istediğimi fark ettim.
Çoğu durumda, tek dilli İngilizce kod tabanlarında bu cevap yeterli olacaktır. Şüpheliyim çünkü buraya gelen çoğu insan bu kategoriye giriyor, bu en popüler cevap. Ancak
bu cevap, her iki metnin de aynı kültür olduğunu ve bu kültürün ne olduğunu bilinceye kadar, metin büyük / küçük harfe duyarsız karşılaşamayacağımız doğal bir problem ortaya çıkarmaktadır. Bu belki daha az popüler bir cevap, ama bence daha doğru ve bu yüzden böyle işaretledim.

Yanıtlar:


1398

Dizenin dizeyi paragraphiçerip içermediğini test etmek için word(thanks @QuarterMeister)

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

Metnin yazıldığı dili tarif cultureetme örneği nerede CultureInfo.

Bu çözüm, dile bağlı olan büyük / küçük harf duyarsızlığının tanımı konusunda şeffaftır . Örneğin, İngilizce dili karakterleri Ive idokuzuncu harfin büyük ve küçük harfleri için kullanılırken, Türk dili bu harfleri 29 harfli alfabesinin onbirinci ve on ikinci harfleri için kullanır . Türkçe 'i' büyük harfli versiyonu, tanıdık olmayan 'İ' karakteridir.

Böylece dizeleri tinve TINaynı kelime vardır İngilizce , ancak farklı kelimeler Türkçe . Anladığım kadarıyla biri 'ruh' anlamına gelirken diğeri onomatopoeia kelimesidir. (Türkler, yanılıyorsam lütfen beni düzeltin veya daha iyi bir örnek önerin)

Özetlemek gerekirse, metnin hangi dilde olduğunu biliyorsanız , yalnızca 'bu iki dize aynı, ancak farklı durumlarda' sorusunu cevaplayabilirsiniz . Eğer bilmiyorsan, bir punt almalısın. İngilizce'nin yazılımdaki hegemonyası göz önüne alındığında, muhtemelen başvurmalısınız CultureInfo.InvariantCulture, çünkü tanıdık şekillerde yanlış olacaktır.


67
Neden olmasın culture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0? Bu, doğru kültürü kullanır ve büyük / küçük harfe duyarsızdır, geçici küçük harf dizeleri ayırmaz ve küçük harfe dönüştürmenin ve karşılaştırmanın her zaman büyük / küçük harf duyarsız bir karşılaştırma ile aynı olup olmadığı sorusunu önler.
Quartermeister

9
Bu çözüm aynı zamanda gereksiz yere bir arama fonksiyonu için bellek ayırarak yığın kirletir
JaredPar

15
İki farklı harf aynı küçük harfe sahipse, ToLower () ile karşılaştırılması büyük / küçük harfe duyarlı olmayan bir IndexOf sonucundan farklı sonuçlar verecektir. Örneğin, U + 0398 "Yunan Büyük Harf Teta" veya U + 03F4 "Yunan Büyük Harf Teta Sembolü" nde ToLower () çağrısı, U + 03B8, "Yunan Küçük Harf Teta" ile sonuçlanır, ancak büyük harfler farklı kabul edilir. Her iki çözüm de U + 0073 "Latin Küçük Harf S" ve U + 017F "Latin Küçük Harf Uzun S" gibi aynı büyük harfle farklı küçük harfleri dikkate alır, böylece IndexOf çözümü daha tutarlı görünür.
Quartermeister

3
@Quartermeister - ve BTW, .NET 2 ve .NET4 bu konuda farklı davrandığını düşünüyorum.
Simon Mourier

10
Neden "ddddfg" .IndexOf ("Df", StringComparison.OrdinalIgnoreCase) yazmadınız?
Chen

2713

String.IndexOf Yöntemini kullanabilir ve kullanılacak StringComparison.OrdinalIgnoreCasearama türü olarak iletebilirsiniz :

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

Daha da iyisi dize için yeni bir uzantı yöntemi tanımlamaktır:

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

Unutmayın, eski sürüm kullanımı için C # 6.0'dan (VS 2015) beri boş yayılma ?. kullanılabilir

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

KULLANIM:

string title = "STRING";
bool contains = title.Contains("string", StringComparison.OrdinalIgnoreCase);

3
Harika dize genişletme yöntemi! .IndexOf () gerçekleştirirken herhangi bir nesne referans hatası oluşmasını önlemek için kaynak dizginin boş olmadığını kontrol etmek için mayın düzenledim.
Richard Pursehouse

8
Bu aynı cevabı verir paragraph.ToLower(culture).Contains(word.ToLower(culture))ile CultureInfo.InvariantCultureve herhangi bir yerelleştirme sorunları çözmez. Neden aşırı karmaşık şeyler? stackoverflow.com/a/15464440/284795
Albay Panic

60
@ColonelPanic ToLowersürümü bir karşılaştırma / arama işleminde gereksiz olan 2 ayırma içerir. Neden gerektirmeyen bir senaryoda gereksiz yere tahsis edilmeli?
Mart'ta JaredPar

4
@Seabiscuit o olmaz iş nedeniyle stringbir olduğunu IEnumerable<char>dolayısıyla alt dizeleri bulmak için kullanamazsınız
JaredPar

6
Uyarı kelimesi: için varsayılan değer string.IndexOf(string)geçerli kültürü, varsayılan değer string.Contains(string)ise sıralı karşılaştırıcıyı kullanmaktır. Bildiğimiz gibi, birincisi daha uzun bir aşırı yük seçerken değiştirilebilir, ikincisi değiştirilemez. Bu tutarsızlığın bir sonucu aşağıdaki kod örneğidir: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

Bunun gibi kullanabilirsiniz IndexOf():

string title = "STRING";

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

0 (sıfır) bir dizin olabileceğinden -1'e karşı kontrol edersiniz.

MSDN

Bu dize bulunursa değerin sıfır temelli dizin konumu veya bulunmuyorsa -1. Değer String.Empty ise, dönüş değeri 0'dır.


148

Regex kullanarak alternatif çözüm:

bool contains = Regex.IsMatch("StRiNG to search", Regex.Escape("string"), RegexOptions.IgnoreCase);

6
İyi Fikir, ayrıca RegexOptions'da RegexOptions.IgnoreCase & RegexOptions.IgnorePatternWhitespace & RegexOptions.CultureInvariant;herkes için olduğu gibi birçok bitwise kombinasyonumuz var .
Saravanan

7
Düzgünlük için IsMatch kullanarak rağmen bu yöntemi tercih söylemek gerekir.
wonea

31
Daha da kötüsü, arama dizesi normal ifade olarak yorumlandığından, bazı noktalama işaretleri yanlış sonuçlara neden olur (veya geçersiz bir ifade nedeniyle bir istisnayı tetikler). Aramayı deneyin "."içinde "This is a sample string that doesn't contain the search string". Veya "(invalid"bu konuyu aramayı deneyin .
cHao

17
@cHao: Bu durumda Regex.Escapeyardımcı olabilir. Regex, IndexOf/ extension Containsbasit (ve tartışmasız daha açık) olduğunda hala gereksiz görünüyor .
Dan Mangiarelli

6
Bu Regex çözümünün en iyi yol olduğunu ima etmediğimi unutmayın. Sadece asıl gönderilen soruya cevaplar listesine ekliyordu "Aşağıdaki dönüş doğru yapmak için bir yolu var mı?".
Jed

79

Her zaman önce dizeleri yukarı veya küçük harflerle yazabilirsiniz.

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

Hata! Sadece son parçayı gördüm. Büyük / küçük harfe duyarlı olmayan bir karşılaştırma *muhtemelen *aynı şeyi yapar ve performans bir sorun değilse, büyük harfli kopyalar oluşturma ve bunları karşılaştırma konusunda bir sorun görmüyorum. Bir zamanlar büyük / küçük harf duyarsız bir karşılaştırma gördüğüme yemin edebilirdim ...


122
"Türkiye testi" için arama yap :)
Jon Skeet

7
Bazı Fransız yerel ayarlarında, büyük harflerin aksan işaretleri yoktur, bu nedenle ToUpper (), ToLower () 'dan daha iyi olmayabilir. Varsa uygun araçları kullanın - büyük / küçük harfe duyarlı olmayan karşılaştırma.
Blair Conrad

5
ToUpper veya ToLower kullanmayın ve Jon
Skeet'in söylediklerini yapmayın

14
Sadece bunu iki yıl sonra tekrar gördüm ve yeni bir aşağı oy ... neyse, ben dizeleri karşılaştırmak için daha iyi yollar olduğunu kabul ediyorum. Bununla birlikte, tüm programlar yerelleştirilmez (çoğu olmaz) ve birçoğu dahili veya atılabilir uygulamalardır. Atılan uygulamalar için en iyi tavsiye için kredi beklemek zor beri ... Devam ediyorum: D
Ed S.

8
"Türkiye testi" araması, "TÜRKİYE TESTİ" aramasıyla aynı mıdır?
JackAce

55

Yalnızca .NET Core 2.0+ (şu andan itibaren)

.NET Core, sürüm 2.0'dan beri bununla başa çıkmak için bir çift yöntem kullanmıştır:

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

Misal:

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

Zamanla, muhtemelen .NET Standardına ve oradan da Base Class Library'nin diğer tüm uygulamalarına geçeceklerdir.



52

Yanıtla ilgili bir sorun, bir dize null olduğunda bir istisna atmasıdır. Bunu çek olarak ekleyebilirsiniz, böylece:

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

8
ToCheck boş dize ise, Contains belgelerine göre true değerini döndürmelidir: "value parametresi bu dize içinde gerçekleşirse veya değer boş dize (" ") ise true; aksi halde false."
amurra

3
Yukarıdaki amurra yorumuna dayanarak, önerilen kodun düzeltilmesi gerekmez mi? Ve bu, kabul edilen cevaba eklenmemeli, böylece en iyi yanıt ilk önce olacak mı?
David White

13
Kaynak boş bir dize veya nCheck olursa olsun null olursa, şimdi bu true değerini döndürecektir. Bu doğru olamaz. Ayrıca toCheck boş bir dize ve kaynak null değilse IndexOf zaten true değerini döndürür. Burada gerekli olan null için bir çek. (Source == null || value == null) false döndürürse öneririm;
Colin

2
Kaynak boş olamaz
Lucas

1
if (string.IsNullOrEmpty(source)) return string.IsNullOrEmpty(toCheck);
Kyle Delaney

35

StringExtension sınıf yoludur, tam bir kod örneği vermek için yukarıdaki yazıların birkaçını birleştirdim:

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

neden başka bir soyutlama katmanına izin veriyorsunuz StringComparison?
l --''''''---------------- '' '' '' '' '' ''

35

Bu temiz ve basit.

Regex.IsMatch(file, fileNamestr, RegexOptions.IgnoreCase)

31
Yine de bu bir örüntü ile eşleşecektir. Eğer örnekte, fileNamestrherhangi bir özel regex karakterler var (örneğin *, +, .vs.) o zaman oldukça bir sürpriz bekliyor olacak. Bu çözümü uygun bir Containsişlev gibi çalıştırmanın tek yolu fileNamestryaparak kaçmaktır Regex.Escape(fileNamestr).
XåpplI'-I0llwlg'I -

ayrıca, normal ifadenin ayrıştırılması ve eşleştirilmesi, büyük / küçük harfe duyarlı olmayan bir karşılaştırmaya göre çok daha kaynak yoğun
phuclv

29

OrdinalIgnoreCase, CurrentCultureIgnoreCase veya InvariantCultureIgnoreCase?

Bu eksik olduğu için, hangisinin ne zaman kullanılacağı hakkında bazı öneriler:

Dos

  • StringComparison.OrdinalIgnoreCaseKültür-agnostik dize eşleşmesi için güvenli varsayılan olarak karşılaştırmalar için kullanın .
  • StringComparison.OrdinalIgnoreCaseDaha yüksek hız için karşılaştırmalar kullanın .
  • StringComparison.CurrentCulture-basedÇıktıyı kullanıcıya görüntülerken dize işlemlerini kullanın .
  • Dilsel olmayan StringComparison.Ordinalveya StringComparison.OrdinalIgnoreCasekarşılaştırma
    dilsel olarak alakasız olduğunda (örneğin sembolik) değişmez kültüre dayalı olarak dize işlemlerinin geçerli kullanımını değiştirin .
  • Karşılaştırma için dizeleri normalleştirmek ToUpperInvariantyerine kullanın ToLowerInvariant.

Yapılmaması Gerekenler

  • Dize karşılaştırma mekanizmasını açıkça veya dolaylı olarak belirtmeyen dize işlemleri için aşırı yükler kullanın.
  • Çoğu durumda StringComparison.InvariantCulturetemelli dize
    işlemleri kullanın ; birkaç istisnadan biri
    dilsel olarak anlamlı fakat kültürel olarak agnostik verilerden kaynaklanıyor olabilir.

Bu kurallara dayanarak şunları kullanmalısınız:

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

oysa [Kararınız] yukarıdaki önerilere bağlıdır.

kaynağın bağlantısı: http://msdn.microsoft.com/en-us/library/ms973919.aspx


ya her zaman ingilizce bir dize alacağını biliyorsan. hangisini kullanmalı?
BKSpurgeon

1
@BKSpurgeon OrdinalIgnoreCase kullanırım, eğer durum önemli değilse
Fabian Bigler

20

Bunlar en kolay çözümlerdir.

  1. Endeksine göre

    string title = "STRING";
    
    if (title.IndexOf("string", 0, StringComparison.CurrentCultureIgnoreCase) != -1)
    {
        // contains 
    }
  2. Durum değiştirerek

    string title = "STRING";
    
    bool contains = title.ToLower().Contains("string")
  3. Regex adlı geliştiriciden

    Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);

11

Bu C # olmadığını biliyorum, ama çerçeve (VB.NET) zaten böyle bir işlevi var

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

C # varyantı:

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

11

InStrEğer uluslararası ilgili kaygı duyan (veya bunu reimplement olabilir) eğer VisualBasic gelen yöntem düzeneği en iyisidir. İçine bakarken dotNeetPeek, yalnızca büyük harf ve küçük harf değil, aynı zamanda kana tipi ve tam ve yarım genişlikli karakterleri de (Roma alfabesinin tam genişlikli sürümleri olmasına rağmen çoğunlukla Asya dilleri için geçerlidir) açıkladığını gösterir. ). Bazı ayrıntıları atlıyorum, ancak özel yönteme göz atın 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);
}


8

Bunu kullan:

string.Compare("string", "STRING", new System.Globalization.CultureInfo("en-US"), System.Globalization.CompareOptions.IgnoreCase);

26
Soru soran Containsaramıyor Compare.
DuckMaestro

@DuckMaestro, kabul edilen cevap uyguluyor Containsile IndexOf. Yani bu yaklaşım da aynı derecede faydalı! Bu sayfadaki C # kodu örneği string.Compare () kullanıyor. SharePoint ekibinin tercihi!
vulcan kuzgun

6

Bu, buradaki diğer örneğe oldukça benziyor, ancak enum'u boole basitleştirmeye karar verdim, birincil olarak diğer alternatiflere normalde gerek yok. İşte benim örnek:

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

Ve kullanım şöyle bir şeydir:

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

6

RegEx kullanmak bunu yapmanın basit bir yoludur:

Regex.IsMatch(title, "string", RegexOptions.IgnoreCase);

4
Cevabınız tam olarak guptat59 ile aynıdır, ancak cevabında belirtildiği gibi, bu normal bir ifadeyle eşleşir, bu nedenle test ettiğiniz dize herhangi bir özel regex karakteri içeriyorsa, istenen sonucu vermez.
Casey

2
Bu, bu cevabın doğrudan bir kopyasıdır ve bu cevapta belirtilenle aynı sorunlardan muzdariptir
Liam

Kabul. Düzenli ifadeleri inceleyin
Jared

5

Sadece buradaki cevaba dayanmak için, bunu biraz daha kullanıcı dostu hale getirmek için bir dize uzantısı yöntemi oluşturabilirsiniz:

    public static bool ContainsIgnoreCase(this string paragraph, string word)
    {
        return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;
    }

1
Paragrafınızın ve kelimenizin her zaman ABD'de olacağını varsayarsak
Boris Callens

3
Kültürü ABD'ye zorlamaktan kaçınmak için return CultureInfo.CurrentCulture.CompareInfo.IndexOf(paragraph, word, CompareOptions.IgnoreCase) >= 0;bunun yerine kullanın.
AndrewWhalan

3

iletilen dizenizin dizede olup olmadığını kontrol etmek istiyorsanız bunun için basit bir yöntem vardır.

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

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

Dize içeriyorsa veya olmasa bu boole değeri döndürülür



2
if ("strcmpstring1".IndexOf(Convert.ToString("strcmpstring2"), StringComparison.CurrentCultureIgnoreCase) >= 0){return true;}else{return false;}

2

string.indexof ()Fonksiyonu kullanabilirsiniz . Bu büyük / küçük harfe duyarsız olacaktır


2

Buradaki hile, dizeyi aramak, durumu görmezden gelmek, ancak tam olarak aynı tutmaktır (aynı durumda).

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

Çıktı "Sıfırla"


-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
}

-4

Yeni başlayanlar için basit bir yol:

title.ToLower().Contains("string");//of course "string" is lowercase.

Sadece yanlış olduğu için aşağı oy. Başlık = StRiNg ise ne olur? StRiNg! = String ve StRiNg! = STRING
berniefitz

Ben hatalıydım. Cevabı aşağıdaki gibi düzenleyin, çok basit basit: <br/> title.ToLower (). İçerir ("string") // elbette "string" küçük
harftir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.