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




unity string contains case insensitive (16)

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.


.NET Core 2.0+ uniquement (à partir de maintenant)

.NET Core a eu une paire de méthodes pour résoudre ce problème depuis la version 2.0:

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

Exemple:

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

Avec le temps, ils entreront probablement dans .NET Standard et, à partir de là, dans toutes les autres implémentations de la bibliothèque de classes de base.


C'est propre et simple.

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

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

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)

Juste comme ça:

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

La classe StringExtension est la voie à suivre. J'ai combiné quelques-uns des articles ci-dessus pour donner un exemple de code complet:

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

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"


Pour tester si le paragraph chaîne contient le word chaîne (merci @QuarterMeister)

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

culture est l'instance de CultureInfo décrivant la langue dans laquelle le texte est écrit.

Cette solution est transparente en ce qui concerne la définition de l’insensibilité à la casse, qui dépend de la langue . Par exemple, la langue anglaise utilise les caractères I et i pour les versions majuscules et minuscules de la neuvième lettre, tandis que la langue turque utilise ces caractères pour les onzième et douzième lettres de son alphabet long de 29 lettres. La version turque en majuscule de «i» est le caractère inconnu «İ».

Ainsi, les chaînes tin et TIN sont le même mot en anglais , mais des mots différents en turc . Si je comprends bien, l’un signifie «esprit» et l’autre est un mot onomatopée. (Turcs, corrigez-moi si je me trompe, ou suggérez un meilleur exemple)

Pour résumer, vous ne pouvez répondre à la question "ces deux chaînes sont-elles identiques, mais dans des cas différents" si vous savez dans quelle langue se trouve le texte . Si vous ne savez pas, vous devrez prendre une punt. Compte tenu de l'hégémonie anglaise des logiciels, vous devriez probablement recourir à CultureInfo.InvariantCulture , car ce sera une erreur de façon familière.


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

Utiliser un RegEx est un moyen simple de faire ceci:

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

Vous pouvez toujours juste commencer par monter ou descendre les cordes.

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

Oops, je viens de voir ce dernier morceau. Une comparaison insensible à la casse * ferait * probablement * la même chose de toute façon, et si les performances ne sont pas un problème, je ne vois pas de problème pour créer des copies majuscules et les comparer. J'aurais juré avoir déjà vu une comparaison insensible à la casse ...


Vous pouvez utiliser IndexOf() comme ceci:

string title = "STRING";

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

Puisque 0 (zéro) peut être un index, vous vérifiez par -1.

MSDN

Position d'index de base zéro de la valeur si cette chaîne est trouvée ou -1 si ce n'est pas le cas. Si value est String.Empty, la valeur de retour est 0.


Vous pouvez utiliser la fonction string.indexof () . Ce sera insensible à la casse


si vous voulez vérifier si votre chaîne passée est dans la chaîne, il existe une méthode simple pour cela.

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

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

This boolean value will return if string contains or not

OrdinalIgnoreCase, CurrentCultureIgnoreCase ou InvariantCultureIgnoreCase?

Comme cela manque, voici quelques recommandations sur le moment d'utiliser lequel:

Dos

  • Utilisez StringComparison.OrdinalIgnoreCase pour les comparaisons comme valeur par défaut sûre pour la correspondance de chaînes StringComparison.OrdinalIgnoreCase de la culture.
  • Utilisez les comparaisons StringComparison.OrdinalIgnoreCase pour augmenter la vitesse.
  • Utilisez des opérations de chaîne StringComparison.CurrentCulture-based lors de l'affichage du résultat à l'utilisateur.
  • Basculez l'utilisation actuelle des opérations de chaîne basées sur la culture invariante pour utiliser StringComparison.Ordinal ou StringComparison.OrdinalIgnoreCase non linguistique lorsque la comparaison est effectuée.
    linguistiquement non pertinent (symbolique, par exemple).
  • Utilisez ToUpperInvariant plutôt que ToLowerInvariant lors de la normalisation de chaînes pour la comparaison.

À ne pas faire

  • Utilisez des surcharges pour les opérations sur les chaînes qui ne spécifient pas explicitement ou implicitement le mécanisme de comparaison des chaînes.
  • Utiliser StringComparison.InvariantCulture chaîne basée sur StringComparison.InvariantCulture
    opérations dans la plupart des cas; une des rares exceptions serait
    données persistantes linguistiquement significatives mais culturellement agnostiques.

Sur la base de ces règles, vous devriez utiliser:

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

alors que [YourDecision] dépend des recommandations ci-dessus.

lien de source: http://msdn.microsoft.com/en-us/library/ms973919.aspx


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






case-insensitive