在字符串中查找第一个大写字母出现的正则表达式

3

我希望找到字符串中第一个大写字母的索引。

例如:

String x = "soHaM";

对于这个字符串,索引应该返回2。在发现第一个大写字母后,正则表达式应忽略所有其他大写字母。如果没有发现大写字母,则应返回0。请帮助。


4
为什么要使用正则表达式(Regex)? - Nikhil Agrawal
当然可以!为什么不只使用循环呢? - Dan Puzey
6个回答

5
我非常确定您只需要正则表达式A-Z \p{Lu}:
public static class Find
{
  // Apparently the regex below works for non-ASCII uppercase
  // characters (so, better than A-Z).
  static readonly Regex CapitalLetter = new Regex(@"\p{Lu}");

  public static int FirstCapitalLetter(string input)
  {
    Match match = CapitalLetter.Match(input);

    // I would go with -1 here, personally.
    return match.Success ? match.Index : 0;
  }
}

你尝试过这个吗?

6
好的。请注意,如果您使用0作为返回值表示没有大写字母,那么您无法区分第一个字母是大写还是根本没有大写字母的情况。 - buckley
@buckley:我同意,这看起来很奇怪。 - Dan Tao
是的,我被错误地复制粘贴了。正确的应该是 \p{Lu} 或者如果你更喜欢逐字字符串,则为 @"\p{Lu}"。 - buckley
使用for循环真的会有性能问题吗?我以为正则表达式会更快。 - Soham Dasgupta
@SohamDasgupta,正则表达式只会循环调用Char.IsUpper(或其道义等效物之一)。它不可能比循环更快,而且可能至少会慢一点。最好的情况是它可能更快、更容易编写、更可读或更易于维护。(虽然对于这么简单的东西,可能以上都不是最好的选择。) - Joe White
显示剩余2条评论

5

仅供娱乐,以下是一个LINQ解决方案:

string x = "soHaM";
var index = from ch in x.ToArray()
            where Char.IsUpper(ch)
            select x.IndexOf(ch);

这将返回 IEnumerable<Int32>。如果你想要第一个大写字母的索引,只需调用 index.First() 或仅检索 LINQ 中的第一个实例:

string x = "soHaM";
var index = (from ch in x.ToArray()
            where Char.IsUpper(ch)
            select x.IndexOf(ch)).First();

编辑

如评论中所建议的,这里提供另一种LINQ方法(可能比我最初的建议更有效):

string x = "soHaM";
x.Select((c, index) => new { Char = c, Index = index }).First(c => Char.IsUpper(c.Char)).Index;

2
更快: x.Select((c, index) => new { Char = c, Index = index }).First(c => Char.IsUpper(c.Char)).Index; - Tim Schmelter
@JamesHill 抱歉,James,我被困在2.0版本了。 - Soham Dasgupta
如果没有大写字符,调用.First()将抛出异常。这可以处理,或者您可以使用.FirstOrDefault,如果没有大写字符,则返回0。如果您正在使用此LINQ查询来修剪字符串开头的非大写字符,则使用带有查询的.FirstOrDefault()将在没有大写字符的情况下返回整个未更改的字符串(在x.Substring(index)的情况下)。 - MCattle

4

无需使用 Regex

int firstUpper = -1;
for(int i = 0; i < x.Length; i++)
{
    if(Char.IsUpper(x[i]))
    {
        firstUpper = i;
        break;
    }
}

http://msdn.microsoft.com/en-us/library/system.char.isupper.aspx

为了完整起见,这里是我使用LINQ的方法(尽管即使OP可以使用它,这不是正确的工具):

int firstUpperCharIndex = -1;
var upperChars = x.Select((c, index) => new { Char = c, Index = index })
                  .Where(c => Char.IsUpper(c.Char));
if(upperChars.Any())
    firstUpperCharIndex = upperChars.First().Index;

3

首先,如果该方法在您的情况下返回0,则意味着该列表中的第一个字符为大写,因此建议将-1表示未找到或抛出异常。

无论如何,仅仅因为你可以使用正则表达式并不一定是最好的选择,此外它们通常很慢且难以阅读,使您的代码更难处理。

无论如何,这是我的贡献。

    public static int FindFirstUpper(string text)
    {
        for (int i = 0; i < text.Length; i++)
            if (Char.IsUpper(text[i]))
                return i;

        return -1;
    }

1

使用循环

 int i = 0;
 for(i = 0; i < mystring.Length; i++)
 {
   if(Char.IsUpper(mystring, i))
    break;
 }

i 是你应该关注的值;


1

使用 Linq:

using System.Linq;

string word = "soHaMH";
var capChars = word.Where(c => char.IsUpper(c)).Select(c => c);
char capChar = capChars.FirstOrDefault();
int index = word.IndexOf(capChar); 

使用C#:

using System.Text.RegularExpressions;

string word = "soHaMH";
Match match= Regex.Match(word, "[A-Z]");
index = word.IndexOf(match.ToString());

有人能解释一下 .Select(c => c) 这部分的含义吗?谢谢。 - swenflea

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