c# string == - Groß- und Kleinschreibung nicht berücksichtigt 'Enthält (Zeichenfolge)'




12 Answers

Sie können die String.IndexOf-Methode verwenden und StringComparison.OrdinalIgnoreCase als den zu verwendenden StringComparison.OrdinalIgnoreCase :

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

Noch besser ist es, eine neue Erweiterungsmethode für string zu definieren:

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

Beachten Sie diese Nullausbreitung ?. ist seit C # 6.0 (VS 2015) verfügbar, für ältere Versionen

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

VERWENDUNGSZWECK:

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

Gibt es eine Möglichkeit, die folgenden Ergebnisse wahr zu machen?

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

Es scheint keine Überlastung zu geben, die es mir erlaubt, die Groß- / Kleinschreibung einzustellen. Momentan ÜBERZEUGE ich beide, aber das ist blöd (womit ich mich auf die i18n Probleme beziehe, die mit Up- und Down-Casing einhergehen).

AKTUALISIEREN
Diese Frage ist uralt und seitdem ist mir klar, dass ich um eine einfache Antwort auf ein wirklich umfangreiches und schwieriges Thema gebeten habe, wenn Sie es gründlich untersuchen wollen.
In den meisten Fällen reicht this Antwort bei einsprachigen englischen Codebasen aus. Ich vermute, da die meisten Leute, die hierher kommen, in diese Kategorie fallen, ist dies die beliebteste Antwort.
This Antwort wirft jedoch das inhärente Problem auf, dass wir nicht zwischen Groß- und Kleinschreibung unterscheiden können, bis wir wissen, dass beide Texte dieselbe Kultur sind und wir wissen, was diese Kultur ist. Dies ist vielleicht eine weniger beliebte Antwort, aber ich denke, es ist richtiger und deshalb habe ich sie als solche markiert.




Alternative Lösung mit Regex:

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

Beachten

Wie @cHao in seinem Kommentar hervorgehoben hat, gibt es Szenarien, die dazu führen, dass diese Lösung falsche Ergebnisse liefert. Stellen Sie sicher, dass Sie wissen, was Sie tun, bevor Sie diese Lösung zufällig implementieren.




Ein Problem mit der Antwort ist, dass eine Ausnahme ausgelöst wird, wenn eine Zeichenfolge null ist. Sie können das als Kontrolle hinzufügen, damit es nicht funktioniert:

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



Das ist sauber und einfach.

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



Genau wie dieser:

string s="AbcdEf";
if(s.ToLower().Contains("def"))
{
    Console.WriteLine("yes");
}



Ich weiß, dass dies nicht das C # ist, aber im Framework (VB.NET) gibt es bereits eine solche Funktion

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

C # Variante:

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



Letztendlich kommt es bei einer generischen "Enthält" -Operation auf eine Funktion wie diese,

/// <summary>
/// Determines whether the source contains the sequence.
/// </summary>
/// <typeparam name="T">The type of the items in the sequences.</typeparam>
/// <param name="sourceEnumerator">The source enumerator.</param>
/// <param name="sequenceEnumerator">The sequence enumerator.</param>
/// <param name="equalityComparer">An equality comparer.</param>
/// <remarks>
/// An empty sequence will return <c>true</c>.
/// The sequence must support <see cref="IEnumerator.Reset"/>
/// if it does not begin the source.
/// </remarks>
/// <returns>
/// <c>true</c> if the source contains the sequence;
/// otherwise <c>false</c>.
/// </returns>
public static bool Contains<T>(
    IEnumerator<T> sourceEnumerator,
    IEnumerator<T> sequenceEnumerator,
    IEqualityComparer<T> equalityComparer)
{
    if (equalityComparer == null)
    {
        equalityComparer = EqualityComparer<T>.Default;
    }

    while (sequenceEnumerator.MoveNext())
    {
        if (sourceEnumerator.MoveNext())
        {
            if (!equalityComparer.Equals(
                sourceEnumerator.Current,
                sequenceEnumerator.Current))
            {
                sequenceEnumerator.Reset();
            }
        }
        else
        {
            return false;
        }
    }

    return true;
}

Dies kann trivial in einer Erweiterungsversion eingeschlossen werden, die IEnumerable wie IEnumerable akzeptiert.

public static bool Contains<T>(
        this IEnumerable<T> source,
        IEnumerable<T> sequence,
        IEqualityComparer<T> equalityComparer = null)
{
    if (sequence == null)
    {
        throw new ArgumentNullException("sequence");
    }

    using(var sequenceEnumerator = sequence.GetEnumerator())
    using(var sourceEnumerator = source.GetEnumerator())
    {
        return Contains(
            sourceEnumerator,
            sequenceEnumerator,
            equalityComparer);
    }
}

Dies funktioniert nun für den ordinalen Vergleich beliebiger Sequenzen, einschließlich Zeichenfolgen, da string IEnumerable<char> implementiert.

// The optional parameter ensures the generic overload is invoked
// not the string.Contains() implementation.
"testable".Contains("est", EqualityComparer<char>.Default)

Wie wir wissen, sind Strings nicht generisch, sondern spezialisiert. Es gibt zwei Schlüsselfaktoren.

  1. Das Thema "Gehäuse" hat selbst verschiedene sprachabhängige Randfälle.
  2. Die eher umstrittene Frage, wie ein Satz von "Textelementen" (Buchstaben / Zahlen / Symbole usw.) durch Unicode-Codepunkte dargestellt wird, und welche gültigen Zeichenfolgen eine gegebene Zeichenfolge darstellen können, werden die Details in these answers .

Der Nettoeffekt ist der gleiche. Zeichenketten, von denen Sie behaupten, dass sie sprachlich gleich sind, können durch verschiedene Kombinationen von Zeichen gültig dargestellt werden. Außerdem ändern sich die Gültigkeitsregeln zwischen den Kulturen.

All dies führt zu einer spezialisierten String-basierten Implementierung von "Enthält".

using System.Globalization;

public static bool Contains(
         this string source,
         string value,
         CultureInfo culture = null,
         CompareOptions options = CompareOptions.None)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }

    var compareInfo = culture == null ? 
            CultureInfo.CurrentCulture.CompareInfo :
            culture.CompareInfo;

    var sourceEnumerator = StringInfo.GetTextElementEnumerator(source);
    var sequenceEnumerator = StringInfo.GetTextElementEnumerator(value);

    while (sequenceEnumerator.MoveNext())
    {
        if (sourceEnumerator.MoveNext())
        {
            if (!(compareInfo.Compare(
                    sourceEnumerator.Current,
                    sequenceEnumerator.Current,
                    options) == 0))
            {
                sequenceEnumerator.Reset();
            }
        }
        else
        {
            return false;
        }
    }

    return true;
}

Diese Funktion kann verwendet werden, um unabhängig von der Groß- und Kleinschreibung normale, kultivierungsspezifische "enthält" auszuführen. z.B

"testable".Contains("EST", StringComparer.CurrentCultureIgnoreCase)



Dies ist dem anderen Beispiel hier ziemlich ähnlich, aber ich habe mich entschlossen, die Aufzählung mit bool zu vereinfachen, weil andere Alternativen normalerweise nicht erforderlich sind. Hier ist mein Beispiel:

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

Und Verwendung ist so etwas wie:

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



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



Der Trick hier besteht darin, nach der Zeichenfolge zu suchen und die Groß- / Kleinschreibung zu ignorieren, sie jedoch genau gleich zu halten (mit derselben Groß- / Kleinschreibung).

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

Ausgabe ist "Reset"




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
}



Einfacher Weg für Neulinge:

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



Related