Reputation: 3039
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
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
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
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
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