BestPractice - Chuyển đổi ký tự đầu tiên của chuỗi thành chữ thường


136

Tôi muốn có một phương thức biến đổi ký tự đầu tiên của chuỗi thành chữ thường.

Cách tiếp cận của tôi:

1.

public static string ReplaceFirstCharacterToLowerVariant(string name)
{
    return String.Format("{0}{1}", name.First().ToString().ToLowerInvariant(), name.Substring(1));
}

2.

public static IEnumerable<char> FirstLetterToLowerCase(string value)
{
    var firstChar = (byte)value.First();
    return string.Format("{0}{1}", (char)(firstChar + 32), value.Substring(1));
}

Cách tiếp cận của bạn là gì?

Câu trả lời:


239

Tôi sẽ sử dụng cách ghép đơn giản:

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

Giải pháp đầu tiên không được tối ưu hóa vì string.Format chậm và bạn không cần nó nếu bạn có định dạng sẽ không bao giờ thay đổi. Nó cũng tạo ra một chuỗi bổ sung để chuyển đổi chữ cái thành chữ thường, không cần thiết.

Cách tiếp cận với "+ 32" là xấu / không thể duy trì được vì nó đòi hỏi kiến ​​thức về các giá trị bù của ký tự ASCII. Nó cũng sẽ tạo đầu ra không chính xác với dữ liệu Unicode và các ký tự ký hiệu ASCII.


4
tôi sẽ làm điều đó:char.ToLower(name[0]).ToString() + name.Substring(1)
Andrey

7
@Rookian: +toán tử chậm khi bạn nối nhiều chuỗi. Trong trường hợp đó, a StringBuildersẽ thực hiện tốt hơn nhiều. Tuy nhiên, +nhanh hơn nhiều string.Format. Sử dụng cái sau khi bạn thực sự cần định dạng một cái gì đó (như hiển thị số nguyên, nhân đôi hoặc ngày).
Dirk Vollmar

6
@ 0x03: nó chỉ chậm nếu bạn nối nhiều chuỗi lặp lại. Nếu bạn ghép tất cả chúng trong một thao tác, +toán tử hoàn toàn không chậm, bởi vì trình biên dịch biến nó thành một String.Concat(tuy nhiên String.Joinnhanh hơn so String.Concatvới một số lý do ngớ ngẩn).
Thorarin

2
Một phương pháp nhanh hơn là: chuỗi tĩnh công khai ToFirstLetterLower (chuỗi văn bản) {var charArray = text.ToCharArray (); charArray [0] = char.ToLower (charArray [0]); trả về chuỗi mới (charArray); }
Matteo Migliore

2
Tôi đã sử dụng tiện ích mở rộng public static string ToLowerFirst(this string source) { if (string.IsNullOrWhiteSpace(source)) return source; var charArray = source.ToCharArray(); charArray[0] = char.ToLower(charArray[0]); return new string(charArray); } Dựa trên nhận xét của @ MatteoMigliore.
KregHEk

64

Tùy thuộc vào tình huống, một chút lập trình phòng thủ có thể được mong muốn:

public static string FirstCharacterToLower(string str)
{
    if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        return str;

    return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}

Các iftuyên bố cũng ngăn cản một chuỗi mới được xây dựng nếu nó sẽ không được thay đổi anyway. Thay vào đó, bạn có thể muốn phương thức bị lỗi khi nhập null và ném một ArgumentNullException.

Như mọi người đã đề cập, sử dụng String.Formatcho việc này là quá mức cần thiết.


Sửa lỗi cho tôi nếu tôi sai nhưng str.Sub chuỗi (1) sẽ trả về ký hiệu ở vị trí 1 vì số đếm cho phương thức này không được chỉ định. vì vậy bạn sẽ có char [0] trong chữ thường + char ở vị trí 1 Vì vậy, tôi thích loại bỏ một char bắt đầu từ char đầu tiên trong chuỗi. Kết quả là chuỗi không có chữ cái đầu tiên. Sau đó, tôi sẽ thêm chuỗi này vào char đầu tiên được chuyển đổi thành chữ thường
fedotoves

3
@ B-Rain: xem xét bản thân đã sửa: msdn.microsoft.com/en-us/l
Library / hxthx5h6% 28VS.90% 29.aspx

7

Chỉ trong trường hợp nó giúp bất cứ ai tình cờ vấp phải câu trả lời này.

Tôi nghĩ rằng đây sẽ là phương thức mở rộng tốt nhất, sau đó bạn có thể gọi nó bằng yourString.FirstCharacterToLower ();

public static class StringExtensions
{
    public static string FirstCharacterToLower(this string str)
    {
        if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
        {
            return str;
        }

        return Char.ToLowerInvariant(str[0]) + str.Substring(1);
    }
}

3

Của tôi là

if (!string.IsNullOrEmpty (val) && val.Length > 0)
{
    return val[0].ToString().ToLowerInvariant() + val.Remove (0,1);   
}

3
Tôi tò mò, tại sao val.Remove? Có vẻ hơi phản trực giác với tôi.
Thorarin

@Thorarin rõ ràng vì bạn muốn xóa char đầu tiên (vì bạn đang thêm phiên bản chữ thường ở phía trước)
Riki

2

Tôi thích câu trả lời được chấp nhận, nhưng bên cạnh việc kiểm tra string.IsNullOrEmptytôi cũng sẽ kiểm tra xem Char.IsLower(name[1])trong trường hợp bạn đang xử lý từ viết tắt. Ví dụ, bạn sẽ không muốn "AIDS" trở thành "aIDS".


7
IMO đây là trách nhiệm của người gọi
onof

1

Giải pháp nhanh nhất tôi biết mà không lạm dụng c #:

public static string LowerCaseFirstLetter(string value)
{
    if (value?.Length > 0)
    {
        var letters = value.ToCharArray();
        letters[0] = char.ToLowerInvariant(letters[0]);
        return new string(letters);
    }
    return value;
}

0

Kết hợp một vài và làm cho nó một phần mở rộng chuỗi. Đã thêm ngắn mạch trên khoảng trắng và không chữ.

public static string FirstLower(this string input) => 
    (!string.IsNullOrWhiteSpace(input) && input.Length > 0 
        && char.IsLetter(input[0]) && !char.IsLower(input[0]))
    ? input[0].ToString().ToLowerInvariant() + input.Remove(0, 1) : input;

0

Đây là một phương pháp mở rộng nhỏ bằng cách sử dụng cú pháp mới nhất và xác nhận chính xác

public static class StringExtensions
{
    public static string FirstCharToLower(this string input)
    {
        switch (input)
        {
            case null: throw new ArgumentNullException(nameof(input));
            case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
            default: return input.First().ToString().ToLower() + input.Substring(1);
        }
    }
}

1
Không chắc chắn nếu ném một ngoại lệ sẽ là giải pháp tốt nhất. Chuỗi là null hay rỗng, chỉ cần trả về chuỗi null hoặc chuỗi rỗng.
R. de Veen

Nếu String là null hoặc rỗng, hoạt động sẽ không có ý nghĩa vì không có char đầu tiên thay đổi thành chữ thường.
Carlos Muñoz

0

Dùng cái này:

string newName= name[0].ToString().ToLower() + name.Substring(1);

-3

Nó là tốt hơn để sử dụng String.Concathơn String.Formatnếu bạn biết rằng định dạng không thay đổi dữ liệu, và chỉ cần ghép nối là mong muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.