通过 C# 将破折号分隔的字符串转换为驼峰命名法

Convert Dash-Separated String to camelCase via C#

我有一个很大的 XML 文件,其中包含实现以破折号分隔的命名约定的标签名称。如何使用 C# 将标签名称转换为驼峰式命名约定?

规则是: 1.将所有字符转为小写 2. 将每个破折号后的第一个字符大写 3. 删除所有破折号

例子 转换前

<foo-bar>
 <a-b-c></a-b-c>
</foo-bar>

转换后

<fooBar>
 <aBC></aBC>
</fooBar>

这是一个有效的代码示例,但处理起来很慢 - 我认为有更好的方法来实现我的目标。

string ConvertDashToCamelCase(string input)
{
    input = input.ToLower();
    char[] ca = input.ToCharArray();
    StringBuilder sb = new StringBuilder();

    for(int i = 0; i < ca.Length; i++)
    {
        if(ca[i] == '-')
        {
            string t = ca[i + 1].ToString().toUpper();
            sb.Append(t);
            i++;
        }
        else
        {
            sb.Append(ca[i].ToString());
        }
    }

    return sb.ToString();
}
string ConvertDashToCamelCase(string input)
{
    string[] words = input.Split('-');

    words = words.Select(element => wordToCamelCase(element));

    return string.Join("", words);
}

string wordToCamelCase(string input)
{
    return input.First().ToString().ToUpper() + input.Substring(1).ToLower();
}

您的原始代码运行缓慢的原因是您在不必要的地方到处调用 ToString。没有那个必要。也不需要 char 的中间数组。下面应该快得多,而且比使用 String.Split 的版本还要快。

string ConvertDashToCamelCase(string input)
{
    StringBuilder sb = new StringBuilder();
    bool caseFlag = false;
    for (int i = 0; i < input.Length; ++i)
    {
        char c = input[i];
        if (c == '-')
        {
            caseFlag = true;
        }
        else if (caseFlag)
        {
            sb.Append(char.ToUpper(c));
            caseFlag = false;
        }
        else
        {
            sb.Append(char.ToLower(c));
        }
    }
    return sb.ToString();
}

我不会声称以上是最快的。事实上,有几个明显的优化可以节省一些时间。但是上面的内容很清楚:很容易理解。

关键是caseFlag,你用它来指示下一个复制的字符应该设置为大写。另请注意,我不会自动将整个字符串转换为小写。没有理由这样做,因为无论如何您都会查看每个字符,并且可以在那个时候进行适当的转换。

这里的想法是,代码不会做比它绝对必须做的更多的工作。

这是@Jim Mischel 的回答的更新版本,它将忽略内容 - 即它只会使用驼峰式标签名称。

string ConvertDashToCamelCase(string input)
{
    StringBuilder sb = new StringBuilder();
    bool caseFlag = false;
    bool tagFlag = false; 
    for(int i = 0; i < input.Length; i++)
    {   
        char c = input[i];
        if(tagFlag)
        {
            if (c == '-')
            {
                caseFlag = true;
            }
            else if (caseFlag)
            {
                sb.Append(char.ToUpper(c));
                caseFlag = false;
            }
            else
            {
                sb.Append(char.ToLower(c));
            }
        }
        else
        {
            sb.Append(c);
        }

        // Reset tag flag if necessary
        if(c == '>' || c == '<')
        {
            tagFlag = (c == '<');
        }

    }
    return sb.ToString();
}
using System;
using System.Text;

public class MyString
{
  public static string ToCamelCase(string str)
  {
    char[] s = str.ToCharArray();
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < s.Length; i++)
    {
      if (s[i] == '-' || s[i] == '_')
        sb.Append(Char.ToUpper(s[++i]));
      else
        sb.Append(s[i]);
    }
    return sb.ToString();
  }
}

为了完整起见,这里还有一行正则表达式(由 启发):

string ConvertDashToCamelCase(string input) =>
    Regex.Replace(input, "-.", m => m.Value.ToUpper().Substring(1));

它将所有出现的 -x 替换为转换为大写的 x


特殊情况:

  • 如果您希望所有其他字符都小写,请在表达式中将 input 替换为 input.ToLower()

      string ConvertDashToCamelCase(string input) =>
          Regex.Replace(input.ToLower(), "-.", m => m.Value.ToUpper().Substring(1));
    
  • 如果您希望在单词之间支持多个破折号 (dash--case) 并删除所有破折号 (dashCase),请将 - 替换为 -+ 在正则表达式中(贪婪地匹配所有破折号序列)并只保留最后一个字符:

      string ConvertDashToCamelCase(string input) =>
          Regex.Replace(input, "-+.", m => m.Value.ToUpper().Substring(m.Value.Length - 1));
    
  • 如果要支持单词之间的多个破折号 (dash--case) 并仅删除最后一个破折号 (dash-Case),请更改正则表达式以仅匹配后面的破折号通过非破折号(而不是破折号后跟任何字符):

      string ConvertDashToCamelCase(string input) =>
          Regex.Replace(input, "-[^-]", m => m.Value.ToUpper().Substring(1));