将C#中的TitleCase字符串转换为camelCase字符串

106

我有一个字符串,我将其转换为TextInfo.ToTitleCase并删除了下划线,然后将字符串连接在一起。现在我需要将字符串中的第一个字符且仅第一个字符改为小写,但由于某种原因,我无法想出如何实现。

class Program
{
    static void Main(string[] args)
    {
        string functionName = "zebulans_nightmare";
        TextInfo txtInfo = new CultureInfo("en-us", false).TextInfo;
        functionName = txtInfo.ToTitleCase(functionName).Replace('_', ' ').Replace(" ", String.Empty);
        Console.Out.WriteLine(functionName);
        Console.ReadLine();
    }
}

结果: ZebulansNightmare

期望结果: zebulansNightmare

更新:

class Program
{
    static void Main(string[] args)
    {
        string functionName = "zebulans_nightmare";
        TextInfo txtInfo = new CultureInfo("en-us", false).TextInfo;
        functionName = txtInfo.ToTitleCase(functionName).Replace("_", string.Empty).Replace(" ", string.Empty);
        functionName = $"{functionName.First().ToString().ToLowerInvariant()}{functionName.Substring(1)}";
        Console.Out.WriteLine(functionName);
        Console.ReadLine();
    }
}

产生所需的输出。


3
您应该直接发布自己的答案,而不是将解决方案放在问题中,这样会更加令人困惑。 - StayOnTarget
19个回答

136

注意:我的回答已过时,请查看下面this的答案,它使用System.Text.Json,这个库可用于dotnet core或通过nuget用于旧版dotnet框架应用程序

原始回答:

您只需要将数组中的第一个字符转换为小写即可。请参阅answer

Char.ToLowerInvariant(name[0]) + name.Substring(1)

作为一个附注,由于您正在删除空格,因此可以将下划线替换为空字符串。
.Replace("_", string.Empty)

10
这在缩写词开头不起作用(例如,VATReturnAmount)。请参见我的回答 - Mojtaba
2
同意@Mojtaba的观点。如果您想要与ASP.NET中的camelCase JSON序列化兼容,请不要使用此选项。开头的缩写词不会保持一致。 - Craig Shearer
3
在.NET Core C#9中,你可以使它更加简洁:return char.ToLowerInvariant(s[0]) + s[1..]; 的意思是将字符串的第一个字符转换为小写,并将其与从第二个字符到结尾位置的子字符串拼接起来。 - Matthew M.
1
随着时间的推移,这个答案应该会越来越被踩,而另一个答案(System.Text.Json.JSonNamingPolicy.CamelCase)应该会越来越被赞。 - jeancallisti
1
@jeancallisti - 实际上我的回答应该被删除,但是你不能删除已经被接受的答案。需要有一种方法将某些内容标记为过时或链接到特定的框架。在此期间,我将更新我的答案并指向下面的人。 - Bronumski
显示剩余2条评论

81

如果您正在使用.NET Core 3或.NET 5,您可以调用:

System.Text.Json.JsonNamingPolicy.CamelCase.ConvertName(someString)

这样做将确保您获得与ASP.NET自己的JSON序列化器相同的结果。


1
这对我没有用,它在我的情况下将所有内容转换为小写。 - AussieJoe
3
请注意,这并不会删除空格,因此您需要执行JsonNamingPolicy.CamelCase.ConvertName(str).Replace(" ", string.Empty)。 - Dave
1
@AussieJoe 如果输入字符串(您未提供)全是大写字母,则预期输出字符串为所有小写字母,因为这是标准驼峰命名法处理首字母缩略词的方式。 - jeancallisti

44

将Bronumski的答案实现为扩展方法(不替换下划线)。

 public static class StringExtension
 {
     public static string ToCamelCase(this string str)
     {                    
         if(!string.IsNullOrEmpty(str) && str.Length > 1)
         {
             return char.ToLowerInvariant(str[0]) + str.Substring(1);
         }
         return str.ToLowerInvariant();
     }
 }

 //Or

 public static class StringExtension
 {
     public static string ToCamelCase(this string str) =>
         string.IsNullOrEmpty(str) || str.Length < 2
         ? str.ToLowerInvariant()
         : char.ToLowerInvariant(str[0]) + str.Substring(1);
 }

并使用它:

string input = "ZebulansNightmare";
string output = input.ToCamelCase();

10
我看到的唯一问题是,如果字符串只是"A",它应该返回"a",对吗? - Diogo Luis
不处理驼峰式命名法对缩写的处理方式。我建议使用C#提供的本地函数。 - jeancallisti

20

这是我的代码,如果有用的话

    // This converts to camel case
    // Location_ID => locationId, and testLEFTSide => testLeftSide

    static string CamelCase(string s)
    {
        var x = s.Replace("_", "");
        if (x.Length == 0) return "null";
        x = Regex.Replace(x, "([A-Z])([A-Z]+)($|[A-Z])",
            m => m.Groups[1].Value + m.Groups[2].Value.ToLower() + m.Groups[3].Value);
        return char.ToLower(x[0]) + x.Substring(1);
    }

如果你喜欢使用 Pascal-case:

    static string PascalCase(string s)
    {
        var x = CamelCase(s);
        return char.ToUpper(x[0]) + x.Substring(1);
    }

4
最终提供一个将MYCase转换为myCase的示例,而不是mYCase。谢谢! - Muster Station
@MusterStation 但为什么呢?你不应该一开始就只有"MyCase"吗?如果"Y"是大写的,那么它很可能是另一个单词,对吧? - ygoe
@ygoe 可能是。在“MYCase”中,也许M是一个单词,Y是一个单词,而Case是一个单词。然而,“MY”更可能是一个由两个字母组成的缩写词。例如,“innerHTML”是两个单词,而不是五个。 - John Henckel
为什么你的函数被称为 CamelCase,而实际上它转换成了 PascalCase? :) - Joep Beusenberg
@JoepBeusenberg 好的,我已经修复了。 - John Henckel
显示剩余3条评论

13
以下代码也适用于首字母缩写词。如果它是第一个单词,它会将缩写词转换为小写(例如VATReturn转换为vatReturn),否则保持原样(例如ExcludedVAT转换为excludedVAT)。
name = Regex.Replace(name, @"([A-Z])([A-Z]+|[a-z0-9_]+)($|[A-Z]\w*)",
            m =>
            {
                return m.Groups[1].Value.ToLower() + m.Groups[2].Value.ToLower() + m.Groups[3].Value;
            });

1
谢谢,这样好多了。它与MVC的行为匹配,当您return Json(new { CAPSItem = ... }时,而被接受的答案将创建不匹配。 - NibblyPig
如果你需要将camelCase转换回PascalCase,那么缩写问题就会出现。例如,我不知道如何将vatReturn转换回VATReturn。最好使用VatReturn作为你的帕斯卡命名约定,这样你只需要修改第一个字母即可。 - HappyNomad
@HappyNomad 尽管你的观点在其上下文中是有效的,但问题是关于转换为驼峰命名法(camelCase);这意味着在首字母缩略词中使用VatReturn而不是vatReturn并不是这个问题的答案。 - Mojtaba
稍微扩展一下。上面的正则表达式无法匹配例如 ABC123 (输出为 abC123)。使用 ([A-Z])([A-Z]+|[a-z0-9_]+)($|[A-Z0-9]\w*) 捕获最后一个组中的数字将正确输出 abc123(同时仍然适用于 ABCFoo 等)。 - Doctor Blue
这将是我在原生 .Net 方法之后的第二选择。任何不能处理首字母缩略词的方法都不能被标记为正确答案。 - jeancallisti

6

Example 01

    public static string ToCamelCase(this string text)
    {
        return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text);
    }

示例 02

public static string ToCamelCase(this string text)
    {
        return string.Join(" ", text
                            .Split()
                            .Select(i => char.ToUpper(i[0]) + i.Substring(1)));
    }

Example 03

    public static string ToCamelCase(this string text)
    {
        char[] a = text.ToLower().ToCharArray();

        for (int i = 0; i < a.Count(); i++)
        {
            a[i] = i == 0 || a[i - 1] == ' ' ? char.ToUpper(a[i]) : a[i];

        }
        return new string(a);
    }

5
欢迎来到StackOverflow!尽管这可能回答了问题,但考虑添加文字以说明为什么这是一个合适的答案,并添加支持答案的链接。 - Rick M.
考虑到没有其他答案支持该答案,只有一个链接,我认为这有点苛刻,或者非常“StackOverflow-ish”。肯尼给出的第一个答案在我看来是一个好答案(尽管我同意文本中有一个错别字)。 - s1cart3r
3
那很严厉吗? - CodeWarrior
@CodeWarrior 不,不是的。虽然他本可以说“请”,但是代码风格看起来很丑(可能不只是我这么认为),很难阅读。 - ygoe
2
最重要的是它甚至没有回答问题。它将文本转换为TitleCase,而这并不是所问的问题。 - Joep Beusenberg
TitleCase(无空格)也是PascalCase,它就是CamelCase(大写)。使用“驼峰命名法”这个术语的问题在于通常会假设camelCase必须以小写字母开头,但事实并非如此:)。CamelCase可以以大写字母开头,而PascalCase必须以大写字母开头。在技术设计文档中最好明确指出camelCase或camel case(小写),以避免混淆。假设是不好的,好吗。 - iGanja

5
在 .Net 6 及以上版本中
public static class CamelCaseExtension
{
  public static string ToCamelCase(this string str) => 
     char.ToLowerInvariant(str[0]) + str[1..];
}

不支持处理驼峰缩写词,不能被视为正确。 - jeancallisti
什么是驼峰式缩写? - Xavier John
“驼峰式缩写”是指“驼峰式如何处理任何类型的缩写”。请查看规范(或其他答案),以了解驼峰式如何处理一系列大写字母。 - jeancallisti

4
如果您可以接受Newtonsoft.JSON依赖项,以下字符串扩展方法将会有所帮助。这种方法的优点是序列化与标准WebAPI模型绑定序列化具有相同的高精度性能。
using System;
using Newtonsoft.Json.Serialization;

    public static class StringExtensions
    {
        private class CamelCasingHelper : CamelCaseNamingStrategy
        {
            private CamelCasingHelper(){}
            private static CamelCasingHelper helper =new CamelCasingHelper();
            public static string ToCamelCase(string stringToBeConverted)
            {
                return helper.ResolvePropertyName(stringToBeConverted);     
            }
            
        }
        public static string ToCamelCase(this string str)
        {
            return CamelCasingHelper.ToCamelCase(str);
        }
    }

这是一个工作的fiddle https://dotnetfiddle.net/pug8pP

1
请考虑在顶部编辑您的答案以包括“using”语句。 - jeancallisti
1
添加了使用语句。 - Venkatesh Muniyandi

3

这是根据Leonardo的答案改编的:

static string PascalCase(string str) {
  TextInfo cultInfo = new CultureInfo("en-US", false).TextInfo;
  str = Regex.Replace(str, "([A-Z]+)", " $1");
  str = cultInfo.ToTitleCase(str);
  str = str.Replace(" ", "");
  return str;
}

将字符串转换为帕斯卡命名法,首先在任何大写字母组合前添加一个空格,然后将其转换为标题大小写,最后移除所有的空格。


1
这是我的代码,包括将所有大写前缀转换为小写:
public static class StringExtensions
{
    public static string ToCamelCase(this string str)
    {
        bool hasValue = !string.IsNullOrEmpty(str);

        // doesn't have a value or already a camelCased word
        if (!hasValue || (hasValue && Char.IsLower(str[0])))
        {
            return str;
        }

        string finalStr = "";

        int len = str.Length;
        int idx = 0;

        char nextChar = str[idx];

        while (Char.IsUpper(nextChar))
        {
            finalStr += char.ToLowerInvariant(nextChar);

            if (len - 1 == idx)
            {
                // end of string
                break;
            }

            nextChar = str[++idx];
        }

        // if not end of string 
        if (idx != len - 1)
        {
            finalStr += str.Substring(idx);
        }

        return finalStr;
    }
}

像这样使用:

string camelCasedDob = "DOB".ToCamelCase();

抱歉,但这不是一个好的代码... 连接字符串会创建新的字符串... 在这种情况下,您正在创建与原始字符串 str 相同数量的字符串。如果您有一个很长的字符串,垃圾回收器会讨厌您。 - Legacy Code
想点赞因为它确实处理了驼峰缩写,但最终因为这个答案过于消耗资源而选择了踩。 - jeancallisti

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