获取第n个字符串出现的索引?
题
除非我错过了一个明显的内置方法,否则在字符串中出现 n 字符串的最快方法是什么?
我意识到我可以循环 IndexOf 方法通过在循环的每次迭代中更新其起始索引。但这样做对我来说似乎很浪费。
解决方案
这基本上就是你需要做的 - 或者至少,这是最简单的解决方案。所有你都要“浪费”是n方法调用的成本 - 如果你考虑的话,你实际上不会检查任何案例两次。 (IndexOf会在找到匹配后立即返回,您将继续从停止的位置开始。)
其他提示
你真的可以使用正则表达式 /((s)。*?){n} /
来搜索第n次出现的substring s
。
在C#中,它可能如下所示:
public static class StringExtender
{
public static int NthIndexOf(this string target, string value, int n)
{
Match m = Regex.Match(target, "((" + Regex.Escape(value) + ").*?){" + n + "}");
if (m.Success)
return m.Groups[2].Captures[n - 1].Index;
else
return -1;
}
}
注意:我已将 Regex.Escape
添加到原始解决方案中,以便搜索对正则表达式引擎具有特殊含义的字符。
这基本上就是你需要做的 - 或者至少,这是最简单的解决方案。所有你都要“浪费”是n方法调用的成本 - 如果你考虑的话,你实际上不会检查任何案例两次。 (IndexOf会在找到匹配后立即返回,您将继续从停止的位置开始。)
这是递归实现(上面的 idea )作为扩展方法,模仿框架方法的格式:
public static int IndexOfNth(this string input,
string value, int startIndex, int nth)
{
if (nth < 1)
throw new NotSupportedException("Param 'nth' must be greater than 0!");
if (nth == 1)
return input.IndexOf(value, startIndex);
var idx = input.IndexOf(value, startIndex);
if (idx == -1)
return -1;
return input.IndexOfNth(value, idx + 1, --nth);
}
此外,这里有一些(MBUnit)单元测试可以帮助你(证明它是正确的):
using System;
using MbUnit.Framework;
namespace IndexOfNthTest
{
[TestFixture]
public class Tests
{
//has 4 instances of the
private const string Input = "TestTest";
private const string Token = "Test";
/* Test for 0th index */
[Test]
public void TestZero()
{
Assert.Throws<NotSupportedException>(
() => Input.IndexOfNth(Token, 0, 0));
}
/* Test the two standard cases (1st and 2nd) */
[Test]
public void TestFirst()
{
Assert.AreEqual(0, Input.IndexOfNth("Test", 0, 1));
}
[Test]
public void TestSecond()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 0, 2));
}
/* Test the 'out of bounds' case */
[Test]
public void TestThird()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 0, 3));
}
/* Test the offset case (in and out of bounds) */
[Test]
public void TestFirstWithOneOffset()
{
Assert.AreEqual(4, Input.IndexOfNth("Test", 4, 1));
}
[Test]
public void TestFirstWithTwoOffsets()
{
Assert.AreEqual(-1, Input.IndexOfNth("Test", 8, 1));
}
}
}
private int IndexOfOccurence(string s, string match, int occurence)
{
int i = 1;
int index = 0;
while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
{
if (i == occurence)
return index;
i++;
}
return -1;
}
或在C#中使用扩展方法
public static int IndexOfOccurence(this string s, string match, int occurence)
{
int i = 1;
int index = 0;
while (i <= occurence && (index = s.IndexOf(match, index + 1)) != -1)
{
if (i == occurence)
return index;
i++;
}
return -1;
}
也许使用 String.Split()
方法并检查所请求的事件是否在数组中,如果您不需要索引,但值是索引
经过一些基准测试后,这似乎是最简单,最有效的解决方案
public static int IndexOfNthSB(string input,
char value, int startIndex, int nth)
{
if (nth < 1)
throw new NotSupportedException("Param 'nth' must be greater than 0!");
var nResult = 0;
for (int i = startIndex; i < input.Length; i++)
{
if (input[i] == value)
nResult++;
if (nResult == nth)
return i;
}
return -1;
}
System.ValueTuple ftw:
var index = line.Select((x,i)=&gt;(x,i))。其中(x =&gt; x.Item1 =='&quot;')。ElementAt(5)。项目2; 代码>
从中编写一个函数是作业
这可能会这样做:
Console.WriteLine(str.IndexOf((@"\")+2)+1);