通过C#将Dash-Separated String转换为camelCase

时间:2015-04-28 19:11:51

标签: c# regex string-conversion

我有一个大型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();
}

5 个答案:

答案 0 :(得分:5)

原始代码速度慢的原因是因为您不必要地在整个地方调用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,用于指示复制的下一个字符应设置为大写。另请注意,我不会自动将整个字符串转换为小写字母。没有理由,因为你无论如何都要看每个角色,并且可以在那时进行适当的转换。

这里的想法是代码不会做任何比绝对更多的工作。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

为完整起见,这也是一个正则表达式单行代码(由this JavaScript answer表示):

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

答案 3 :(得分:1)

这是@Jim Mischel的答案的更新版本,它将忽略内容 - 即它只会是camelCase标记名称。

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

答案 4 :(得分:0)

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