Home About

February 11th, 2009

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

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);
        }
    }
}
Be Sociable, Share!

Tags: , ,

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


Most popular
Recent Comments
  • ARS: great plugin! I love it! but, it will be so nice if you can add attribute ‘title’ as one of...
  • Nelson: Saved me from doing it myself. Good article.
  • andy: i am currently playing taiwanese server wow in 奈辛瓦里(PVP) and i would like to realm transfer to somewhere there...
  • berties: any english speaking playing on a taiwanese server?
  • web application development: has C# search volume really so constant over the years? really surprising.