在C#中查找字符串中数字的索引

49

我想从下面的字符串中获取起始数字的索引,请告诉我如何在C#.net中实现。

例如:

University of California, 1980-85.  
University of Colorado, 1999-02 

请提供你目前的代码尝试。 - Mitch Wheat
你想要第一个数字的位置吗? - griegs
是的,我想要获取每个字符串中数字的第一个位置。 - Cool Coder
3个回答

89
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IndexOfAny
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("University of California, 1980-85".IndexOfAny("0123456789".ToCharArray()));
        }
    }
}

这个有性能问题吗?如果我们循环几十个字符串,它会变慢吗? - Emil
我肯定会把ToCharArray放在循环外面。否则,我想这比正则表达式快,但我不能确定。你需要进行性能测试。 - mpen
@mpen 我刚刚尝试了你的建议,但是编译器报错说无法将“string”转换为“char []”。你的建议似乎非常直观,我不确定为什么不起作用,除了“string”具有“char []”的行为和属性之外,实际上并不是一个。 - krillgar
@krillgar,对我来说它仍然有效:https://ideone.com/QwuF12 你没有忘记添加.ToCharArray()这一部分,是吗? - mpen
那我误解了你的评论。你的意思是在进入循环之前创建一个静态字符数组变量,而不是在每次迭代中创建一个变量。看到你现在的回答中的代码,并阅读你的评论,让我认为你试图避免将string转换为char[],这可能需要时间。虽然确实需要这样做,但只需执行一次即可。 - krillgar
1
@krillgar 是的,那正是我所想的 :-) - mpen

10
以下内容可能会帮助您完成任务。
Regex re = new Regex(@"\d+");
Match m = re.Match(txtFindNumber.Text);
if (m.Success) 
{
    lblResults.Text = string.Format("RegEx found " + m.Value + " at position " + m.Index.ToString());
}
else 
{
    lblResults.Text = "You didn't enter a string containing a number!";
}

8

我不确定这是否是最快的方法(我认为它必须比Regex更快),但你可以使用内置的字符串方法IndexOfAny来完成一行代码:

string yourString = "University of California, 1980-85";
int index = yourString.IndexOfAny(new char[]
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
// index = 26
// if nothing found it would be -1

编辑:我在进行的一个简单测试中发现,我的方法似乎要快得多:

string test = "University of California, 1980-85";

System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
long totalTicks1 = 0;
long totalTicks2 = 0;
char[] testChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Regex re = new Regex(@"\d+");
for (int i = 0; i < 1000; i++)
{
    watch.Reset();
    watch.Start();
    Match m = re.Match(test);
    watch.Stop();
    totalTicks1 += watch.ElapsedTicks;

    watch.Reset();
    watch.Start();
    int index = test.IndexOfAny(testChars);
    watch.Stop();
    totalTicks2 += watch.ElapsedTicks;
}

运行结果1:

Regex totalTicks1 = 4851
IndexOfAny totalTicks2 = 1472

运行结果2:

Regex totalTicks1 = 5578
IndexOfAny totalTicks2 = 1470

运行结果3:

Regex totalTicks1 = 5441
IndexOfAny totalTicks2 = 1481

这看起来是一个很大的区别。我想知道不同长度的字符串会如何影响它...除非我真的在寻找某种复杂模式,否则我尽量避免使用Regex,因为它总是感觉非常慢。

编辑2:修正了测试,使其更准确,char[]Regex预定义在循环外部。


你必须运行它数千次才能获得任何形式的准确性,我想。 - mpen
@Mark 我刚刚测试了一下...与此同时你快速地回答了我的问题 :P - Kelsey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接