supprimer - Trouver toutes les positions de la sous-chaîne dans une chaîne plus grande en C#




indexof c# (8)

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

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?


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

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


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}


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

en utilisant LINQ

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

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

Appelez ça comme ceci:

List<int> list = GetPositions("bob is a chowder head bob bob sldfjl", "bob");
// list will contain 0, 22, 26

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




string