c# list contains - Insensible à la casse 'Contient (string)'




12 Answers

Vous pouvez utiliser la méthode String.IndexOf et passer StringComparison.OrdinalIgnoreCase comme type de recherche à utiliser:

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

Encore mieux est de définir une nouvelle méthode d’extension pour string:

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

Notez que cette propagation nulle ?. est disponible depuis C # 6.0 (VS 2015), pour les anciennes versions, utilisez

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

USAGE:

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

Existe-t-il un moyen de rendre vrai le retour suivant?

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

Il ne semble pas exister de surcharge qui me permette de définir la sensibilité à la casse. Pour le moment, je suis en majuscule, mais c’est idiot (je parle ici des problèmes de développement qui vont de haut en bas).

METTRE À JOUR
Cette question est ancienne et depuis lors, je réalise que je vous ai demandé une réponse simple à un sujet très vaste et difficile si vous souhaitez approfondir votre recherche.
Dans la plupart des cas, dans les bases de code anglais unilingues, this réponse suffira. Je soupçonne, car la plupart des gens qui viennent ici tombent dans cette catégorie, c'est la réponse la plus populaire.
This réponse soulève toutefois le problème inhérent que nous ne pouvons pas comparer un texte insensible à la casse tant que nous ne savons pas que les deux textes appartiennent à la même culture et que nous savons quelle est cette culture. C'est peut-être une réponse moins populaire, mais je pense que c'est plus correct et c'est pourquoi je l'ai marquée comme telle.




Solution alternative utilisant Regex:

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

Remarquer

Comme @cHao l'a souligné dans son commentaire, il existe des scénarios susceptibles de provoquer des résultats incorrects pour cette solution. Assurez-vous de savoir ce que vous faites avant de mettre en œuvre cette solution au hasard.




Un problème avec la réponse est qu'il lève une exception si une chaîne est nulle. Vous pouvez ajouter cela comme un chèque pour ne pas:

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



C'est propre et simple.

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



Juste comme ça:

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



Je sais que ce n'est pas le C #, mais dans le framework (VB.NET) il y a déjà une telle fonction

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

Variante C #:

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



En fin de compte, une opération générique "contient" revient à une fonction comme celle-ci,

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

cela peut être trivialement encapsulé dans une version d’extension acceptant IEnumerable comme ceci,

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

Maintenant, cela fonctionnera pour la comparaison ordinale de toutes les séquences, y compris les chaînes, puisque string implémente IEnumerable<char> ,

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

Cependant, comme nous le savons, les chaînes ne sont pas génériques, elles sont spécialisées. Il y a deux facteurs clés en jeu.

  1. Le problème de "casing" qui a lui-même divers cas de bord dépendant de la langue
  2. La question plutôt complexe de savoir comment un ensemble d '"éléments de texte" (lettres / chiffres / symboles, etc.) sont représentés par des points de code Unicode et quelles séquences valides de caractères peuvent représenter une chaîne donnée, les détails sont développés dans these answers .

L'effet net est le même. Les chaînes que vous pouvez affirmer égales sur le plan linguistique peuvent être valablement représentées par différentes combinaisons de caractères. Quoi de plus, les règles de validité changent entre les cultures.

Tout cela mène à une implémentation spécialisée "Contains" basée sur une chaîne, comme celle-ci.

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

Cette fonction peut être utilisée pour réaliser un "contient" qui respecte la casse et qui n’est pas sensible à la casse, quelle que soit la normalisation des chaînes. par exemple

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



Ceci est assez similaire à d'autres exemples ici, mais j'ai décidé de simplifier énum en premier, car d'autres alternatives ne sont normalement pas nécessaires. Voici mon exemple:

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

Et l'utilisation est quelque chose comme:

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



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



Le truc ici est de chercher la chaîne, en ignorant la casse, mais de la garder exactement la même chose (avec la même casse).

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

La sortie est "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
}



Moyen simple pour les débutants:

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



Related