Home About

February 11th, 2009

Manipulating Strings in C# – Finding all occurrences of a string within another string - 5

A common programming problem is to find the position of all copies of a string in another string. For finding the first copy the C# string method IndexOf is similar to the C strpos() function. It returns the first occurrence of a string in another string. But what if you would like to find the position of all occurances of the substring? The following “IndexOfAll” method does just that. It returns an IEnumerable containing the offsets of each sub-string in the main string.

Because you might want to use this code throughout your project it is implemented as an Extension class. Simply put: the IndexOfAll method is attached to the String class. So if we want to call it we can just use .IndexOfAll(needle)

To be able to define an extension we need to create a static method and put it into a static class. The first parameter of the method identifies the class the method should associate with. In our case: string. We do this by defining it as “this string”.

using System;
using System.Collections;

namespace StringItems
{
    static class StringExt
    {
        public static IEnumerable IndexOfAll(this string haystack, string needle)
        {
            int pos,offset = 0;
            while ((pos = haystack.IndexOf(needle))>0)
            {
                haystack = haystack.Substring(pos+needle.Length);
                offset += pos;
                yield return offset;
            }
        }
    }

    class MainClass
    {
        public static void Main(string[] args)
        {
            string needle = "x";
            string haystack = "3 x 4 = 2 x 6 = 1 x 12";
            foreach(int Pos in haystack.IndexOfAll(needle))
                Console.WriteLine("Offset: {0}",Pos);
        }
    }
}
Share and Enjoy:
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google
  • Reddit

Tags: , ,

5 Responses to “Manipulating Strings in C# – Finding all occurrences of a string within another string”

  1. kotelni Says:

    I found IndexOfAll metod call very useful. I like the idea of using yield return.
    This is slightly better version of IndexOfAll, I thought it is worth sharing.
    It does not do Substring in a loop which can give a big performance improvement for large strings and (I think) there was a bug in original version that in ‘while’ comparison must be for >=0 not just >0.

    protected static IEnumerable IndexOfAll(string haystack, string needle)
    {
    int pos;
    int offset = 0;
    int length = needle.Length;
    while ((pos = haystack.IndexOf(needle, offset)) != -1)
    {
    yield return pos;
    offset = pos + length;
    }
    }

  2. Guy Ellis Says:

    Yes – I can confirm that the comparison must be >= and not > otherwise this will fail in cases where the occurrence is at the start of the string.

  3. Lasse Espeholt Says:

    I don’t think these algorithms is very efficient. Instead I think you should look at some algorithms at http://en.wikipedia.org/wiki/List_of_algorithms#Substrings which is designed find multiple substrings instead of using a naive IndexOf loop.

    Best regards, Lasse Espeholt

  4. Hoyb Says:

    Wow!

    Thanks a ton to Kotelni for finding the bug! I just spent 25 minutes trying to figure out why the code above wouldn’t work right (thanks for the effort though, original poster), but I just pasted Kotelni’s code in, and boom, working indexofall function. Thanks again!! You rock!

  5. Mudasir Khan Says:

    ///
    /// Returns the Index of All Occurances of a String
    ///
    /// Original String
    /// String to Find
    ///
    public int[] IndexOfAll(String oString, String sString)
    {
    //List of Occurances
    List sOccurances = new List();
    int pos = 0;
    for (int i = 0; i < oString.Length; i++)
    {
    pos = oString.IndexOf(sString, i);
    if (pos != -1)
    {
    sOccurances.Add(pos);
    i = pos;
    }
    }
    return (int[])sOccurances.ToArray();
    }

Leave a Reply


Recent Comments
  • Ales: Hi, Thanks for the code… I must say I did not experience any errors decrypting any of my messages. I even...
  • JC: Thanks very useful and well explained
  • Thomas: This is a public static class written in the C# language that does not save state. You can call into the...
  • Simon: Thank you very much for this post! It helped me essentially to overcome obstacels to work with mono!
  • Graham: This is a good research for keyboard shortcuts! Some shortcuts are also compatible for Windows OS. I have...