ChatGPT解决这个技术问题 Extra ChatGPT

将所有第一个字母转换为大写,每个单词都小写

我有一串需要转换的文本(大约 5-6 个单词)。

目前,文本如下所示:

THIS IS MY TEXT RIGHT NOW

我想将其转换为:

This Is My Text Right Now

我可以遍历我的字符串集合,但我不确定如何执行此文本修改。


j
jspcal
string s = "THIS IS MY TEXT RIGHT NOW";

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

惊人的!从来不知道那件事。
哈哈真的?那是什么地方?我喜欢 .NET,但有些 API 设计者是真正的混蛋。
请注意,虽然这种方法会按照提问者的要求进行操作,但它是一种简单的算法,它只是将每个单词大写,而不考虑它是什么类型的单词。这并不是真正的“标题大小写”,因为不同语言的标题大小写规则不同。它甚至不适合英语。例如,标题“about a boy”应该是英文的“About a Boy”,但这种方法会给出“About A Boy”。如果您想要真正的标题大小写,则必须编写自己的方法。
我不会称他们为混蛋。 “ToTitleCase”的问题在于它依赖于文化,因此它必须位于 System.Globalization 命名空间中。通过 CurrentThread 只是为了获取线程的当前文化(请注意,如果用户具有不同的区域设置,这可能会导致不同的行为!)。您也可以执行“CultureInfo.InvariantCulture.TextInfo.ToTitleCase()”,这可能会更好,因为 InvariantCulture 在所有文化中的行为都相同。出于兴趣 George:您会将特定于文化的字符串函数放在哪里?
另请注意关于 ALL UPPERCASE 字符串的注释:msdn.microsoft.com/en-us/library/…
P
Peter Mortensen

我可能更喜欢从 CultureInfo (System.Globalization) 调用 ToTitleCase,而不是 Thread.CurrentThread (System.Threading):

string s = "THIS IS MY TEXT RIGHT NOW";
s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

但它应该与 jspcal's solution 相同。

编辑

实际上,这些解决方案不一样CurrentThread --calls--> CultureInfo

System.Threading.Thread.CurrentThread.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Threading.Thread.get_CurrentThread
IL_000B:  callvirt    System.Threading.Thread.get_CurrentCulture
IL_0010:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0015:  ldloc.0     // s
IL_0016:  callvirt    System.String.ToLower
IL_001B:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_0020:  stloc.0     // s

System.Globalization.CultureInfo.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Globalization.CultureInfo.get_CurrentCulture
IL_000B:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0010:  ldloc.0     // s
IL_0011:  callvirt    System.String.ToLower
IL_0016:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_001B:  stloc.0     // s

参考:

文化信息类

Thread.CurrentCulture 属性


P
Peter Mortensen

有几种方法可以将字符串的第一个字符转换为大写。

第一种方法是创建一个方法,该方法简单地将第一个字符加盖并使用子字符串附加字符串的其余部分:

public string UppercaseFirst(string s)
{
    return char.ToUpper(s[0]) + s.Substring(1);
}

第二种方式(稍微快一点)是将字符串拆分为字符数组,然后重新构建字符串:

public string UppercaseFirst(string s)
{
    char[] a = s.ToCharArray();
    a[0] = char.ToUpper(a[0]);
    return new string(a);
}

这个解决方案并不能完全回答这个问题。问题的标题是“将所有首字母转换为大写,每个单词都小写”。但是,此解决方案仅将整个字符串的第一个字母大写。因此,此解决方案会将“hello world”转换为“Hello world”,而不是“Hello World”。
那是个很好的观点。如果您使用类似 string[] words = s.Split(' '); 之类的东西,则可以完成此解决方案然后在foreach(单词中的单词)循环中调用上述方法,重构字符串......其他解决方案似乎更优雅。
M
M.Eren Çelik

如果你在网页上使用,你也可以使用 CSS:

style="text-transform:capitalize;"


为什么选择 CSS?当问题要求 c# asp.net regex
标签 ASP.NET 显示 OP 正在 WEB 上执行此操作。当然,这不是问题的答案,因为 OP 需要 C# 中的解决方案,但它解决了问题并且可以作为替代解决方案。 +1
G
George Mauer

未经测试,但这样的事情应该可以工作:

var phrase = "THIS IS MY TEXT RIGHT NOW";
var rx = new System.Text.RegularExpressions.Regex(@"(?<=\w)\w");
var newString = rx.Replace(phrase,new MatchEvaluator(m=>m.Value.ToLowerInvariant()));

本质上它说“对所有出现在另一个字母数字字符后面的字母数字字符进行正则表达式匹配,然后将其替换为自身的小写版本”


这也使所有大写单词都以大写开头并以小写继续。正是我想要的。
您有时间test it吗?
P
Peter Mortensen

在构建大表时,速度是一个问题,所以 Jamie Dixon's 第二个函数是最好的,但它并不能完全按原样工作......

它无法将所有字母变为小写,并且仅将字符串的第一个字母大写,而不是字符串中每个单词的第一个字母...以下选项解决了这两个问题:

    public string UppercaseFirstEach(string s)
    {
        char[] a = s.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);
    }

虽然在这一点上,这是否仍然是最快的选择还不确定。提供 by George MauerRegex 解决方案可能会更快......足够关心的人应该测试它。


它有效,但我将这个“a.Count()”更改为 a.Length
P
Peter Mortensen

我不知道下面的解决方案是否比 jspcal's answer 更有效,但我很确定它需要比 Jamie'sGeorge's 更少的对象创建。

string s = "THIS IS MY TEXT RIGHT NOW";
StringBuilder sb = new StringBuilder(s.Length);
bool capitalize = true;
foreach (char c in s) {
    sb.Append(capitalize ? Char.ToUpper(c) : Char.ToLower(c));
    capitalize = !Char.IsLetter(c);
}
return sb.ToString();

如果我们关心对象的创建,为什么不使用 for 循环索引在 s 上而不是使用 StringBuilder 就地创建呢?
B
Beyondo

试试这个技巧;它返回所需的结果

CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());

并且不要忘记使用 System.Globalization


“使用 System.Globalization”是什么意思?你能详细说明吗?
@PeterMortensen 据我所知,我认为您只需在 C# 文件的开头键入 using System.Globalization; 即可。
P
Peter Mortensen

除了第一个答案,记得将字符串 selectionstart 索引更改为单词的末尾,否则你会得到字符串中字母的相反顺序。

s.SelectionStart = s.Length;

P
Peter Mortensen

这是您可能感兴趣的可能解决方案之一。在一个循环中从右到左遍历一组字符,反之亦然。

public static string WordsToCapitalLetter(string value)
{
    if (string.IsNullOrWhiteSpace(value))
    {
        throw new ArgumentException("value");
    }

    int inputValueCharLength = value.Length;
    var valueAsCharArray = value.ToCharArray();

    int min = 0;
    int max = inputValueCharLength - 1;

    while (max > min)
    {
        char left = value[min];
        char previousLeft = (min == 0) ? left : value[min - 1];

        char right = value[max];
        char nextRight = (max == inputValueCharLength - 1) ? right : value[max - 1];

        if (char.IsLetter(left) && !char.IsUpper(left) && char.IsWhiteSpace(previousLeft))
        {
            valueAsCharArray[min] = char.ToUpper(left);
        }

        if (char.IsLetter(right) && !char.IsUpper(right) && char.IsWhiteSpace(nextRight))
        {
            valueAsCharArray[max] = char.ToUpper(right);
        }

        min++;
        max--;
    }

    return new string(valueAsCharArray);
}

P
Peter Mortensen

jspcal's answer 作为字符串扩展。

文件程序.cs

class Program
{
    static void Main(string[] args)
    {
        var myText = "MYTEXT";
        Console.WriteLine(myText.ToTitleCase()); //Mytext
    }
}

文件 StringExtensions.cs

using System;
public static class StringExtensions
{

    public static string ToTitleCase(this string str)
    {
        if (str == null)
            return null;

        return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
    }
}