LoginSignup
49
40

More than 5 years have passed since last update.

C# コレクションを指定した文字で連結する

Last updated at Posted at 2013-12-22

前回 に引き続き、ちょっと便利な拡張メソッドについて投稿します。

コレクションを指定した文字で連結してくれるstring.Join()

System.Stringクラスの静的メソッド string.Join()は文字列に変換したコレクションの値を指定した文字で連結してくれます。

public static string Join(string separator, params string[] values);
public static string Join(string separator, params object[] values);
public static string Join(string separator, IEnumerable<string> values);
public static string Join<T>(string separator, IEnumerable<T> values);

配列をログに出力する時などに便利です。
なんでも放り込めるobject の可変長引数を取るオーバーロードもあります。

var intArray = new []{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var str = string.Join( ", ", intArray );
var str2 = string.Join(" : ", DateTime.Now, "hoge", 123, 3.141592 );

Console.WriteLine( "intArray= [ " + str + " ]" );
Console.WriteLine("objects= [ " + str2 + " ]" );

// > intArray= [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
// > objects= [ 2013/12/21 21:42:41 ; hoge ; 123 ; 3.141592 ]

フォーマットを指定してつなげる

各要素のフォーマットを指定したい場合もあります。
こんな感じになりますでしょうか。

var sqrts = Enumerable.Range(1, 10).Select(n => Math.Sqrt(n));
//小数点以下3桁で表示
var str = string.Join(", ", sqrts.Select(x => x.ToString("0.000")));
Console.WriteLine(str);

// > 1.000, 1.414, 1.732, 2.000, 2.236, 2.449, 2.646, 2.828, 3.000, 3.162

こうなると、LINQ的にメソッドチェーンで繋げて書きたくなってきます。

// この語順の方がしっくりきますが、LINQのJoinになってしまいます。
// sqrts.Select(x=>x.ToString("0.000")).Join()
// -> Aggregateで代用できます

var str = sqrts.Select(x=>x.ToString("0.000")).Aggregate((a, b)=>a + ", " + b );
Console.WriteLine(str);

// > 1.000, 1.414, 1.732, 2.000, 2.236, 2.449, 2.646, 2.828, 3.000, 3.162

拡張メソッドにしてスッキリさせる

メソッドチェーンにはなったけれども、Aggregate((a,b)=>a+", "+ b) を余計に記述しなくてはなりません。拡張メソッドに切り出してもう少しスッキリさせてみましょう。

public static class EnumerableExt
{
    public static string ConcatWith(this IEnumerable<double> source, string separator, string format)
    {
        return source.Select(x=>x.ToString(format)).Aggrigate((a,b) => a + separator + b);
    }
}
var sqrts = Enumerable.Range( 1, 10 ).Select( n => Math.Sqrt( n ) );
var str = sqrts.ConcatWith( ", ", "0.000" );

ジェネリックメソッドにする

ジェネリックにしてdouble以外にも対応させましょう。
IFormattable を実装しているクラスであれば対応可能です。

public interface IFormattable
{
    string ToString(string format, IFormatProvider formatProvider);
}
public static class EnumerableExt
{
    public static string ConcatWith<T>(this IEnumerable<T> source, string separator,
        string format, IFormatProvider provider = null) where T : IFormattable
    {
        return source.Select(x => x.ToString( format, provider ))
            .Aggrigate((a,b) => a + separator + b);
    }

    //ついでにフォーマットを指定しないバージョンも
    public static string ConcatWith<T>(this IEnumerable<T> source, string separator)
    {
        return string.Join(separator, source);
    }
}

使用例

Console.WriteLine( new[]{ 1000, 1980, 3980, 4500, 6398 }.ConcatWith(", ", "C") );

var sqrts = Enumerable.Range( 1, 10 ).Select( n => Math.Sqrt( n ) );
Console.WriteLine( sqrts.ConcatWith(", ", "E03") );

var days = new[]{
        new DateTime(2013,1,1),
        new DateTime(2013,2,2),
        new DateTime(2013,3,3)
};
var culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
Console.WriteLine(days.ConcatWith("  ;  ", "D", culture));


// > ¥1,000, ¥1,980, ¥3,980, ¥4,500, ¥6,398
// > 1.000E+000, 1.414E+000, 1.732E+000, 2.000E+000, 2.236E+000, 2.449E+000, 2.646E+000, 2.828E+000, 3.000E+000, 3.162E+000
// > Tuesday, January 1, 2013 ; Saturday, February 2, 2013 ; Sunday, March 3, 2013
49
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
40