簡易文字列置換

static void Main(string[] args)
{
    // {}で括った部分を(ラムダ式/匿名型)を使って置換する
    var input = "食べ物は{tabemono}で飲み物は{nomimono}";
    var r1 = input.Replace(new { tabemono = "たこ焼き", nomimono = "コーラ" });
    var r2 = input.Replace(tabemono => "たこ焼き", nomimono => "コーラ");
}

前も書いたというかJavaScriptでやりましたが、それのC#移植。簡易テンプレート的な文字列置換。ラムダ式版と匿名型版の二つでやってみました。ラムダ式だと、見た目が少し短くて何となく格好良いのですが、変数名の入力時にIntelliSenseが動いてしまうので結構鬱陶しかったり。匿名型のほうはObjectを受け取る関数なので、危なっかしいのが嫌ですね……。

static class Extensions
{
    // 正規表現の|でキーを連結して辞書から置換
    private static string Replace(string input, Dictionary<string, string> dict)
    {
        var pattern = string.Format("{{({0})}}", dict.Select(kvp => Regex.Escape(kvp.Key)).ToJoinedString("|"));
        return Regex.Replace(input, pattern, m => dict[m.Groups[1].Value]);
    }

    /// <param name="anonymousType">{pattern = "replacement"}</param>
    public static string Replace(this string input, Object anonymousType)
    {
        var dict = anonymousType.GetType()
            .GetProperties()
            .ToDictionary(pi => pi.Name, pi => pi.GetValue(anonymousType, null).ToString());
        return Replace(input, dict);
    }

    /// <param name="exprs">pattern => "replacement"</param>
    public static string Replace(this string input, params Expression<Func<Object, string>>[] exprs)
    {
        var dict = exprs.ToDictionary(e => e.Parameters[0].Name, e => e.Compile().Invoke(null));
        return Replace(input, dict);
    }

    // 文字列連結補助メソッド(これないとシンドイので)
    public static string ToJoinedString<T>(this IEnumerable<T> source, string separator)
    {
        var index = 0;
        return source.Aggregate(new StringBuilder(),
                (sb, o) => (index++ == 0) ? sb.Append(o) : sb.AppendFormat("{0}{1}", separator, o))
            .ToString();
    }
}

速度は、匿名型版のほうが圧倒的に速いです。100000回の繰り返しが匿名型だと2秒なのに対してラムダ式版は30秒かかった。Compile().Invokeがアレなんですかねえ。ちなみに、string.Formatでふつーにやった場合は0.03秒でした。まー、でも、メール雛型の置換に、とかちょっとしたことにそこそこ便利に使えるかなー、とは思いつつもっと効率考えてちゃんと組んだ方がいい気もする。

ラムダ式から取り出すのはC# 3.0 における疑似 Map 生成リテラル - NyaRuRuの日記から、匿名型はprototype.jsとかPHPのstrtrとか色々。あとややニッチな Anonymous Types の使い方をまとめてみる (C# 3.0) - NyaRuRuの日記です。

Profile

Yoshifumi Kawai

Cysharp, Inc
CEO/CTO

Microsoft MVP for Developer Technologies(C#)
April 2011
|
July 2024

Twitter:@neuecc GitHub:neuecc

Archive