แปลงตัวอักษรตัวแรกทั้งหมดให้เป็นตัวพิมพ์ใหญ่และวางตัวให้ต่ำลงสำหรับแต่ละคำ


110

ฉันมีสตริงข้อความ (ส่วนใหญ่ประมาณ 5-6 คำ) ที่ต้องแปลง

ขณะนี้ข้อความมีลักษณะดังนี้:

THIS IS MY TEXT RIGHT NOW

ฉันต้องการแปลงเป็น:

This Is My Text Right Now

ฉันสามารถวนซ้ำคอลเลกชันสตริงของฉันได้ แต่ไม่แน่ใจว่าจะดำเนินการแก้ไขข้อความนี้อย่างไร

คำตอบ:


251
string s = "THIS IS MY TEXT RIGHT NOW";

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

31
ฮ่า ๆ จริงๆ? นั่นคือที่มา? ฉันชอบ. NET แต่นักออกแบบ API บางคนก็กระตุกจริงๆ
George Mauer

7
โปรดทราบว่าแม้ว่าวิธีนี้จะทำในสิ่งที่ผู้ถามถาม แต่ก็เป็นอัลกอริธึมไร้เดียงสาที่ใช้ตัวพิมพ์ใหญ่ในแต่ละคำโดยไม่ต้องคำนึงถึงประเภทของคำ ไม่ใช่ "กรณีหัวเรื่อง" จริงๆเนื่องจากกฎสำหรับการใช้ตัวพิมพ์หัวเรื่องแตกต่างกันในภาษาต่างๆ มันไม่ถูกต้องสำหรับภาษาอังกฤษ ตัวอย่างเช่นชื่อ "about a boy" ควรเป็น "About a Boy" ในภาษาอังกฤษ แต่วิธีนี้จะให้ "About A Boy" หากคุณต้องการกรณีชื่อเรื่องจริงคุณจะต้องเขียนวิธีของคุณเอง
Ryan Lundy

18
ฉันจะไม่เรียกพวกเขาว่ากระตุก สิ่งที่มี "ToTitleCase" คือมันขึ้นอยู่กับวัฒนธรรมดังนั้นจึงต้องอยู่ในเนมสเปซ System.Globalization ดำเนินการผ่าน CurrentThread เพื่อรับวัฒนธรรมของเธรดปัจจุบัน (โปรดทราบว่าสิ่งนี้อาจทำให้เกิดพฤติกรรมที่แตกต่างกันหากผู้ใช้มีสถานที่ที่แตกต่างกัน!) คุณสามารถทำ "CultureInfo.InvariantCulture.TextInfo ToTitleCase ()" ได้เช่นกันซึ่งอาจจะดีกว่าเนื่องจาก InvariantCulture ทำงานเหมือนกันในทุกวัฒนธรรม จอร์จไม่สนใจ: คุณจะใส่ฟังก์ชันสตริงเฉพาะวัฒนธรรมไว้ที่ไหน
Michael Stum

3
นอกจากนี้โปรดสังเกตความคิดเห็นเกี่ยวกับสตริงUPPERCASE
Michael Stum

2
วิธีการ toLower () ควรเป็น ToLower () อักษรตัวแรกของวิธีการเริ่มต้นด้วยตัวพิมพ์ใหญ่
Alex

84

ฉันอาจต้องการเรียกใช้ToTitleCaseจากCultureInfo ( System.Globalization ) มากกว่าThread.CurrentThread ( System.Threading )

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

แต่มันควรจะเหมือนกับโซลูชัน jspcal

แก้ไข

จริงๆแล้ววิธีแก้ปัญหาเหล่านั้นไม่เหมือนกัน: CurrentThread- โทร -> 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

อ้างอิง:


16

มีสองวิธีในการแปลงอักขระตัวแรกของสตริงเป็นตัวพิมพ์ใหญ่

วิธีแรกคือสร้างเมธอดที่เพียงแคปอักขระตัวแรกและต่อท้ายสตริงที่เหลือโดยใช้สตริงย่อย:

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

1
โซลูชันนี้ไม่ได้ตอบคำถามอย่างเพียงพอ ชื่อคำถามคือ "แปลงอักษรตัวแรกทั้งหมดเป็นตัวพิมพ์ใหญ่และวางตัวให้ต่ำลงสำหรับแต่ละคำ" อย่างไรก็ตามโซลูชันนี้ใช้อักษรตัวพิมพ์ใหญ่ตัวแรกของสตริงทั้งหมดเท่านั้น ดังนั้นโซลูชันนี้จะแปลง "hello world" เป็น "Hello world" แทนที่จะเป็น "Hello World"
brsfan

9

ยังไม่ทดสอบ แต่สิ่งนี้ควรใช้งานได้:

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

โดยพื้นฐานแล้วจะระบุว่า "เตรียมการจับคู่นิพจน์ทั่วไปในทุกเหตุการณ์ที่เกิดขึ้นของอักขระที่เป็นตัวอักษรและตัวเลขที่ตามหลังอักขระที่เป็นตัวอักษรและตัวเลขอื่นแล้วแทนที่ด้วยตัวพิมพ์เล็กของตัวมันเอง"


คำนี้ยังทำให้คำตัวพิมพ์ใหญ่ทั้งหมดขึ้นต้นด้วยตัวพิมพ์ใหญ่และต่อด้วยตัวพิมพ์เล็ก สิ่งที่ฉันกำลังมองหา
M. Azyoksul

9

หากคุณใช้บนหน้าเว็บคุณสามารถใช้ CSS:

style="text-transform:capitalize;"


2
ทำไมต้อง CSS เมื่อคำถามกำลังถามหาc # asp.net regex
Jay

1
แท็กASP.NETแสดงว่า OP กำลังทำบนเว็บ แน่นอนว่านี่ไม่ใช่คำตอบของคำถามเพราะ OP ต้องการวิธีแก้ปัญหาC#แต่จะช่วยแก้ปัญหาและสามารถเป็นทางเลือกอื่นได้ +1
Muhammad Saqib

6

เมื่อสร้างความเร็วโต๊ะขนาดใหญ่เป็นเรื่องที่น่ากังวลดังนั้นฟังก์ชั่นที่สองของ Jamie Dixon จึงดีที่สุด แต่ก็ไม่ได้ผลอย่างที่เป็นอยู่ ...

ไม่สามารถใช้ตัวอักษรทั้งหมดเป็นตัวพิมพ์เล็กและจะใช้อักษรตัวพิมพ์ใหญ่ตัวแรกของสตริงเท่านั้นไม่ใช่อักษรตัวแรกของแต่ละคำในสตริง ... ตัวเลือกด้านล่างจะแก้ไขปัญหาทั้งสอง:

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

แม้ว่า ณ จุดนี้จะยังคงเป็นตัวเลือกที่เร็วที่สุดหรือไม่นั้นยังไม่แน่นอน แต่Regexวิธีแก้ปัญหาที่ George Mauer ให้มาอาจเร็วกว่า ... คนที่ใส่ใจควรทดสอบ


2
ใช้งานได้ แต่ฉันเปลี่ยน "a.Count ()" นี้เป็น a.Length
Christian

2

ฉันไม่รู้ว่าวิธีแก้ปัญหาด้านล่างมีประสิทธิภาพมากกว่าหรือน้อยกว่าคำตอบของ jspcal แต่ฉันค่อนข้างแน่ใจว่ามันต้องการการสร้างวัตถุน้อยกว่าของเจมี่และจอร์จ

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

1
หากเราเกี่ยวข้องกับการสร้างวัตถุทำไมไม่ทำแทนด้วยการทำดัชนีสำหรับการวนซ้ำบน s แทนที่จะใช้ StringBuilder
jball

0

นอกจากคำตอบแรกแล้วอย่าลืมเปลี่ยน string selectionstart index ไปที่ท้ายคำไม่เช่นนั้นคุณจะได้ลำดับตัวอักษรย้อนกลับในสตริง

s.SelectionStart=s.Length;

0

ลองใช้เทคนิคนี้ ส่งคืนผลลัพธ์ที่ต้องการ

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

และอย่าลืมใช้System.Globalization.


0

หนึ่งในวิธีแก้ปัญหาที่เป็นไปได้ที่คุณอาจสนใจการสำรวจอาร์เรย์ของอักขระจากขวาไปซ้ายและหนีบกลับกันในหนึ่งวง

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

0

คำตอบของ jspcal เป็นส่วนขยายสตริง

Program.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());
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.