【问题标题】:BestPractice - Transform first character of a string into lower caseBestPractice - 将字符串的第一个字符转换为小写
【发布时间】:2010-08-25 10:42:35
【问题描述】:

我想要一个将字符串的第一个字符转换为小写的方法。

我的方法:

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# .net string


    【解决方案1】:

    我会使用简单的连接:

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

    第一个解决方案没有优化,因为string.Format 很慢,如果你有一个永远不会改变的格式,你就不需要它。它还会生成一个额外的字符串来将字母转换为小写,这不是必需的。

    使用“+ 32”的方法很难看/不可维护,因为它需要了解 ASCII 字符值偏移量。它还会使用 Unicode 数据和 ASCII 符号字符生成不正确的输出。

    【讨论】:

    • 我会这样做:char.ToLower(name[0]).ToString() + name.Substring(1)
    • @Rookian:当您连接大量字符串时,+ 运算符很慢。在这种情况下,StringBuilder 的性能会好得多。但是,+string.Format 快得多。当您确实需要格式化某些内容(例如显示整数、双精度数或日期)时,请使用后者。
    • @0x03:只有在迭代地连接大量字符串时才会慢。如果您在一个操作中将它们全部连接起来,+ 运算符一点也不慢,因为编译器会将其转换为 String.Concat(但由于某些愚蠢的原因,String.JoinString.Concat 快)。跨度>
    • 一个更快的方法是: public static string ToFirstLetterLower(string text) { var charArray = text.ToCharArray(); charArray[0] = char.ToLower(charArray[0]);返回新字符串(charArray); }
    • 我使用了扩展名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); } 基于@MatteoMigliore 的评论。
    【解决方案2】:

    根据情况,可能需要一点防御性编程:

    public static string FirstCharacterToLower(string str)
    {
        if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
            return str;
    
        return Char.ToLowerInvariant(str[0]) + str.Substring(1);
    }
    

    if 语句还可以防止构建一个无论如何都不会更改的新字符串。您可能希望该方法在 null 输入上失败,并抛出 ArgumentNullException

    正如人们所提到的,使用String.Format 是矫枉过正的。

    【讨论】:

    • 如果我错了,请纠正我,但 str.Substring(1) 将返回位置 1 的符号,因为未指示此方法的计数。所以你会有小写的 char[0] + 位置 1 的 char 所以我更喜欢从字符串中的第一个字符开始删除一个字符。结果是没有第一个字母的字符串。然后我将此字符串添加到转换为小写的第一个字符
    • @B-Rain:认为自己已得到纠正:msdn.microsoft.com/en-us/library/hxthx5h6%28VS.90%29.aspx
    【解决方案3】:

    以防万一它对偶然发现此答案的任何人有所帮助。

    我认为这将是最好的扩展方法,然后您可以使用 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);
        }
    }
    

    【讨论】:

      【解决方案4】:

      我所知道的不滥用 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;
      }
      

      【讨论】:

        【解决方案5】:

        我的是

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

        【讨论】:

        • 我很好奇,为什么是val.Remove?对我来说似乎有点违反直觉。
        • @Thorarin 显然是因为您想删除第一个字符(因为您要在前面添加小写版本)
        【解决方案6】:

        我喜欢接受的答案,但除了检查 string.IsNullOrEmpty 之外,我还会检查 Char.IsLower(name[1]) 以防您处理缩写。例如。你不希望“艾滋病”变成“艾滋病”。

        【讨论】:

        • IMO 这是调用者的责任
        【解决方案7】:

        结合了一些并使其成为可链接的扩展。在空白和非字母上添加了短路。

        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;
        

        【讨论】:

          【解决方案8】:

          这是一个使用最新语法和正确验证的小扩展方法

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

          【讨论】:

          • 不确定抛出异常是否是最佳解决方案。字符串是null还是空,只返回null还是空字符串。
          • 如果 String 为 null 或为空,则该操作没有意义,因为没有第一个字符可以更改为小写。
          【解决方案9】:

          使用这个:

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

          【讨论】:

            【解决方案10】:

            如果您不想在表达式中两次引用您的字符串,您可以使用System.Linq 执行此操作。

            new string("Hello World".Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())
            

            这样,如果您的字符串来自函数,您就不必存储该函数的结果。

            new string(Console.ReadLine().Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())
            

            【讨论】:

              【解决方案11】:

              如果你关心性能,我会选择

                public static string FirstCharToLower(this string str)
                  => string.Create(str.Length, str, (output, input) =>
                    {
                      input.CopyTo(output);
                      output[0] = char.ToLowerInvariant(input[0]);
                    });
              

              我做了一些快速的基准测试,它似乎至少是此处发布的最快解决方案的两倍,并且比跨多个输入长度的最差解决方案快 3.5 倍。

              没有输入检查,因为它应该是调用者的责任。允许您提前准备数据并进行快速批量处理,而不会因在需要时在热路径中设置分支而减慢速度。

              【讨论】:

                【解决方案12】:

                使用范围运算符 C# 8.0 或更高版本,您可以这样做:

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

                【讨论】:

                  【解决方案13】:

                  如果您知道格式不是更改数据,而只需要连接,那么使用String.Concat 比使用String.Format 更好。

                  【讨论】:

                    猜你喜欢
                    • 2013-09-03
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多