为了账号安全,请及时绑定邮箱和手机立即绑定

获取字符串的第n次出现的索引?

/ 猿问

获取字符串的第n次出现的索引?

青春有我 2019-12-25 15:36:44

除非缺少明显的内置方法,否则在字符串中获取字符串的第n次出现的最快方法是什么?


我意识到我可以通过在每次循环迭代时更新其开始索引来循环IndexOf方法。但是这样做对我来说似乎是浪费。


查看完整描述

3 回答

?
冉冉说

这基本上就是您需要做的-至少,这是最简单的解决方案。您要“浪费”的只是n个方法调用的成本-如果您考虑一下,您实际上将不会两次检查任何一种情况。(IndexOf将在找到匹配项后立即返回,并且您将继续从中断处继续前进。)


查看完整回答
反对 回复 2019-12-25
?
慕的地2183247

您确实可以使用正则表达式/((s).*?){n}/来搜索substring的第n次出现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到原始解决方案中,以允许搜索对正则表达式引擎具有特殊含义的字符。


查看完整回答
反对 回复 2019-12-25
?
UYOU

这基本上就是您需要做的-至少,这是最简单的解决方案。您要“浪费”的只是n个方法调用的成本-如果您考虑一下,您实际上将不会两次检查任何一种情况。(IndexOf将在找到匹配项后立即返回,并且您将继续从中断处继续前进。)


这是作为扩展方法的(上述想法的)递归实现,模仿了框架方法的格式:


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));

        }

    }

}


查看完整回答
反对 回复 2019-12-25

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信