.net d'un - Trouver toutes les positions de la sous-chaîne dans une chaîne plus grande en C#



caractère d'une (10)

J'ai une grande chaîne que j'ai besoin d'analyser, et j'ai besoin de trouver toutes les occurrences de l' extract"(me,i-have lots. of]punctuation , et de stocker l'index de chacune d'elles dans une liste.

Donc disons que ce morceau de corde était au début et au milieu de la plus grande corde, les deux seraient trouvés, et leurs index seraient ajoutés à la List . et la List contiendrait 0 et l'autre index quel qu'il soit.

J'ai joué autour, et la string.IndexOf fait presque ce que je cherche, et j'ai écrit du code - mais ça ne marche pas et j'ai été incapable de comprendre exactement ce qui ne va pas:

List<int> inst = new List<int>();
int index = 0;
while (index < source.LastIndexOf("extract\"(me,i-have lots. of]punctuation", 0) + 39)
{
    int src = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
    inst.Add(src);
    index = src + 40;
}
  • inst = La liste
  • source = La grande chaîne

De meilleures idées?


Answers

public static Dictionary<string, IEnumerable<int>> GetWordsPositions(this string input, string[] Susbtrings)
{
    Dictionary<string, IEnumerable<int>> WordsPositions = new Dictionary<string, IEnumerable<int>>();
    IEnumerable<int> IndexOfAll = null;
    foreach (string st in Susbtrings)
    {
        IndexOfAll = Regex.Matches(input, st).Cast<Match>().Select(m => m.Index);
        WordsPositions.Add(st, IndexOfAll);

    }
    return WordsPositions;
}

Voici un exemple de méthode d'extension pour cela:

public static List<int> AllIndexesOf(this string str, string value) {
    if (String.IsNullOrEmpty(value))
        throw new ArgumentException("the string to find may not be empty", "value");
    List<int> indexes = new List<int>();
    for (int index = 0;; index += value.Length) {
        index = str.IndexOf(value, index);
        if (index == -1)
            return indexes;
        indexes.Add(index);
    }
}

Si vous mettez ceci dans une classe statique et importez l'espace de noms en using , il apparaît comme une méthode sur n'importe quelle chaîne, et vous pouvez simplement faire:

List<int> indexes = "fooStringfooBar".AllIndexesOf("foo");

Pour plus d'informations sur les méthodes d'extension, http://msdn.microsoft.com/en-us/library/bb383977.aspx

De même, en utilisant un itérateur:

public static IEnumerable<int> AllIndexesOf(this string str, string value) {
    if (String.IsNullOrEmpty(value))
        throw new ArgumentException("the string to find may not be empty", "value");
    for (int index = 0;; index += value.Length) {
        index = str.IndexOf(value, index);
        if (index == -1)
            break;
        yield return index;
    }
}

J'ai remarqué qu'au moins deux solutions proposées ne gèrent pas les occurrences de recherche qui se chevauchent. Je n'ai pas vérifié celui marqué avec la coche verte. Voici un qui gère les hits de recherche qui se chevauchent:

    public static List<int> GetPositions(this string source, string searchString)
    {
        List<int> ret = new List<int>();
        int len = searchString.Length;
        int start = -1;
        while (true)
        {
            start = source.IndexOf(searchString, start +1);
            if (start == -1)
            {
                break;
            }
            else
            {
                ret.Add(start);
            }
        }
        return ret;
    }

En fonction du code que j'ai utilisé pour trouver plusieurs occurrences d'une chaîne dans une chaîne plus grande, votre code ressemblerait à ceci:

List<int> inst = new List<int>();
int index = 0;
while (index >=0)
{
    index = source.IndexOf("extract\"(me,i-have lots. of]punctuation", index);
    inst.Add(index);
    index++;
}

Version polie + support ignorant le cas:

public static int[] AllIndexesOf(string str, string substr, bool ignoreCase = false)
{
    if (string.IsNullOrWhiteSpace(str) ||
        string.IsNullOrWhiteSpace(substr))
    {
        throw new ArgumentException("String or substring is not specified.");
    }

    var indexes = new List<int>();
    int index = 0;

    while ((index = str.IndexOf(substr, index, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) != -1)
    {
        indexes.Add(index++);
    }

    return indexes.ToArray();
}

en utilisant LINQ

public static IEnumerable<int> IndexOfAll(this string sourceString, string subString)
{
    return Regex.Matches(sourceString, subString).Cast<Match>().Select(m => m.Index);
}

@csam est correct en théorie, bien que son code ne soit pas conforme et puisse être réfracté

public static IEnumerable<int> IndexOfAll(this string sourceString, string matchString)
{
    matchString = Regex.Escape(matchString);
    return from Match match in Regex.Matches(sourceString, matchString) select match.Index;
}

Sans Regex, en utilisant le type de comparaison de chaînes:

string search = "123aa456AA789bb9991AACAA";
string pattern = "AA";
Enumerable.Range(0, search.Length)
   .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
   .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length),StringComparison.OrdinalIgnoreCase))
   .Select(searchbit => searchbit.Index)

Cela renvoie {3,8,19,22}. Un motif vide correspondrait à toutes les positions.

Pour plusieurs modèles:

string search = "123aa456AA789bb9991AACAA";
string[] patterns = new string[] { "aa", "99" };
patterns.SelectMany(pattern => Enumerable.Range(0, search.Length)
   .Select(index => { return new { Index = index, Length = (index + pattern.Length) > search.Length ? search.Length - index : pattern.Length }; })
   .Where(searchbit => searchbit.Length == pattern.Length && pattern.Equals(search.Substring(searchbit.Index, searchbit.Length), StringComparison.OrdinalIgnoreCase))
   .Select(searchbit => searchbit.Index))

Cela renvoie {3, 8, 19, 22, 15, 16}


Salut belle réponse par @Matti Virkkunen

public static List<int> AllIndexesOf(this string str, string value) {
    if (String.IsNullOrEmpty(value))
        throw new ArgumentException("the string to find may not be empty", "value");
    List<int> indexes = new List<int>();
    for (int index = 0;; index += value.Length) {
        index = str.IndexOf(value, index);
        if (index == -1)
            return indexes;
        indexes.Add(index);
        index--;
    }
}

Mais cela couvre des cas de tests comme AOOAOOA où la sous-chaîne

sont AOOA et AOOA

Sortie 0 et 3


Utilisez les méthodes toLowerCase ou toLocaleLowerCase de l'objet String . La différence est que toLocaleLowerCase prendra en compte les paramètres régionaux actuels de l'utilisateur / hôte. Conformément au § 15.5.4.17 de la spécification du langage ECMAScript (ECMA-262) , toLocaleLowerCase ...

... fonctionne exactement de la même manière que LOWERCASE sauf que son résultat est destiné à produire le résultat correct pour les paramètres régionaux actuels de l'environnement hôte, plutôt qu'un résultat indépendant des paramètres régionaux. Il y aura seulement une différence dans les quelques cas (tels que le turc) où les règles pour ce langage entrent en conflit avec les mappages de cas Unicode habituels.

Exemple:

var lower = 'Your Name'.toLowerCase();

Notez également que les fonctions toLowerCase et toLocaleLowerCase sont implémentées pour fonctionner de manière générique sur n'importe quel type de valeur. Vous pouvez donc appeler ces fonctions même sur des objets non- String . Cela impliquera la conversion automatique en une valeur de chaîne avant de changer le cas de chaque caractère dans la valeur de chaîne résultante. Par exemple, vous pouvez appliquer toLowerCase directement à une date comme celle-ci:

var lower = String.prototype.toLowerCase.apply(new Date());

et qui est effectivement équivalent à:

var lower = new Date().toString().toLowerCase();

La seconde forme est généralement préférée pour sa simplicité et sa lisibilité. Sur les versions antérieures d'IE, le premier avait l'avantage de pouvoir fonctionner avec une valeur null . Le résultat de l'application toLowerCase ou toLocaleLowerCase sur null produirait null (et pas une condition d'erreur).





c# .net asp.net string