【问题标题】:What is the best way to String.Join a non-string array?String.Join 非字符串数组的最佳方法是什么?
【发布时间】:2011-03-12 09:03:17
【问题描述】:

在第二个例子中,String.Join 非字符串数组的简写方式是什么?

string[] names = { "Joe", "Roger", "John" };
Console.WriteLine("the names are {0}", String.Join(", ", names)); //ok

decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m };
Console.WriteLine("the prices are {0}", String.Join(", ", prices)); //bad overload

【问题讨论】:

    标签: c# string arrays join


    【解决方案1】:

    如果你有LINQ:

    decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
    Console.WriteLine("the prices are {0}", 
        String.Join(", ", 
           prices.Select(p => p.ToString()).ToArray()
        )
    );
    

    【讨论】:

    • 请注意,如果您不使用 .NET 4,则需要致电 ToArray()
    • 我会 +1,除了这会创建第二个数组,这对于给出的简单示例来说很好,但在现实世界中是一个不好的习惯。
    • 如果您使用的是 .NET 4,则根本不需要 LINQ。 string.Join(", ", prices);
    【解决方案2】:
    Console.WriteLine("the prices are {0}", String.Join(", ", Array.ConvertAll(prices, p => p.ToString()));
    

    【讨论】:

      【解决方案3】:

      我有两个 Delimit 函数可以为我执行此操作。
      它们的占用空间非常小,因为没有创建第二个数组,并且在返回字符串的地方,在幕后使用了 StringBuilder,因此它不会复制和连接到相同的字符串,从而导致更长的连接延迟。
      因此,它们对于非常大和/或长度未知的系列很有用。

      第一个写入 TextWriter 并且不返回任何内容,第二个返回一个字符串,并委托给第一个传入的 StringWriter。

      public static void Delimit<T>(this IEnumerable<T> me, System.IO.TextWriter writer, string delimiter)
      {
          var iter = me.GetEnumerator();
          if (iter.MoveNext())
              writer.Write(iter.Current.ToString());
      
          while (iter.MoveNext())
          {
              writer.Write(delimiter);
              writer.Write(iter.Current.ToString());
          }
      }
      
      public static string Delimit<T>(this IEnumerable<T> me, string delimiter)
      {
          var writer = new System.IO.StringWriter();
          me.Delimit(writer, delimiter);
          return writer.ToString();
      }
      

      所以考虑到高于你的价格

      decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
      Console.WriteLine("the prices are {0}", prices.Delimit(", "));
      

      decimal[] prices = { 39.99M, 29.99m, 29.99m, 19.99m, 49.99m }; 
      Console.Write("the prices are ")
      prices.Delimit(System.Console.Out, ", ");
      Console.WriteLine();
      

      【讨论】:

      • 创建 StringWriter 而不是 Array 有很多开销吗?我有一个类似的函数来创建分隔字符串,它添加了用于创建 CSV 的文本限定符。
      • CK:对于小型阵列,可能不是(唯一确定的方法是分析它们)。问题在于非常大的数组或未知大小的序列。另外,如果你有一个十进制值列表,你会先在列表上调用 .ToArray 吗?在某些时候,您需要将容器复制到 Array 以使 .Join 工作。对我来说 linq 的乐趣在于我可以停止思考不同的集合类型及其包含的内容,而只需以最小的开销编写通用代码。
      【解决方案4】:

      ck 停止的地方开始,将其提取到一个方法中以使其可重用:

      public static class EnumerableExtensions {
        public static string Join<T>(this IEnumerable<T> self, string separator) { 
          if (self == null) throw new ArgumentNullException();
          if (separator == null) throw new ArgumentNullException("separator");
          return String.Join(separator, self.Select(e => e.ToString()).ToArray());
        }
      }
      

      现在用法更具可读性:

      Console.WriteLine("the prices are {0}", prices.Join(", "));
      
      【解决方案5】:

      可以使用 linq 转换为字符串:

      Console.WriteLine("the prices are {0}", String.Join(", ", prices.Select(p => p.ToString()).ToArray()));
      

      或使用 Aggregate() 代替 string.Join()

      Console.WriteLine("the prices are {0}",
          prices.Select(p => p.ToString()).
                .Aggregate((total, p) => total + ", " + p));
      

      甚至(格式略有不同)

      Console.WriteLine(
          prices.Select(p => p.ToString()).
                .Aggregate("the prices are", (total, p) => total + ", " + p));
      

      【讨论】:

        猜你喜欢
        • 2010-10-17
        • 1970-01-01
        • 2016-01-03
        • 1970-01-01
        • 1970-01-01
        • 2011-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多