AsValeO
AsValeO

Reputation: 3039

C# string.IndexOfNthFromEnd() extension method

I've found a nice extension method that finds Nth occurrence of value into some input string:

public static int IndexOfNth(this string input, string value, int startIndex, int nth)
{
    if (nth < 1)
        throw new ArgumentException("Can not find the zeroth index of substring in string. Must start with 1");
    if (nth == 1)
        return input.IndexOf(value, startIndex, StringComparison.Ordinal);
    var idx = input.IndexOf(value, startIndex, StringComparison.Ordinal);
    if (idx == -1)
        return -1;
    return input.IndexOfNth(value, idx + value.Length, --nth);
}

I need the next one, but can't transform it myself:

IndexOfNthFromEnd(this string input, string value, int nth)

It should find index of Nth occurrence from end of the string. For example:

IndexOfNthFromEnd("-!-!----", "!", 2) // = 1;
IndexOfNthFromEnd("-!-!----", "!", 1) // = 3;
IndexOfNthFromEnd("-!-!----", "-!", 2) // = 0;
IndexOfNthFromEnd("-!-!----", "-!", 1) // = 2;

Upvotes: 2

Views: 217

Answers (4)

Alper Tunga Arslan
Alper Tunga Arslan

Reputation: 579

Try this and please look this example

private static int IndexOfNth(string str, char c, int n) {
    int s = -1;

    for (int i = 0; i < n; i++) {
        s = str.IndexOf(c, s + 1);

        if (s == -1) break;
    }

    return s;
}

Upvotes: 1

Keith Hall
Keith Hall

Reputation: 16085

public static int IndexOfNthFromEnd(this string input, string value, int startIndex, int nth)
{
    if (nth < 1)
        throw new ArgumentException("Can not find the zeroth index of substring in string. Must start with 1");
    var idx = input.LastIndexOf(value, startIndex, StringComparison.Ordinal);
    if (idx == -1 || nth == 1)
        return idx;
    return input.IndexOfNthFromEnd(value, idx - value.Length, --nth);
}

Note that your original IndexOfNth should really do:

return input.IndexOfNth(value, idx + value.Length, --nth);

otherwise for: "abababa".IndexOfNth("bab", 0, 2) it returns 3, when it should be -1 because bab only appears in the string once.

Upvotes: 1

Cole Cameron
Cole Cameron

Reputation: 2233

Here is an iterative approach keeping the signature outlined in your question (i.e., without a start index parameter). It's probably not the most efficient approach if your string contains a lot of repetition, but it works. I also haven't added any of the lovely parameter validation from the original routine.

public static int IndexOfNthFromEnd(this string input, string value, int nth)
{
    var newString = input;
    var index = 0;

    while (nth-- > 0 && index >= 0)
    {
        index = newString.LastIndexOf(value);
        newString = newString.Substring(0, index);
    }

    return index;
}

Upvotes: 1

Richard
Richard

Reputation: 850

Perhaps not the most elegant solution but you could reverse the input string using:

    char[] charArray = s.ToCharArray();
    Array.Reverse( charArray );
    (new string( charArray )).IndexOfNth("-!-!----", "!", 2);

and use the same extension method.

Upvotes: 0

Related Questions