6

バックグラウンド

私は最近、.NET 4 の System.String クラスに Join メソッドの新しいオーバーロードがあることを読みました。この新しいオーバーロードは区切り記号を取り、IEnumerable<T>中間の文字列配列に変換する必要なく、任意のコレクションを 1 つの文字列に結合できるようにします。

涼しい!つまり、これを実行できるようになりました。

var evenNums = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0);
var list = string.Join(",",evenNums);

...これの代わりに:

var evenNums = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .Select(i => i.ToString())
    .ToArray();
var list = string.Join(",", evenNums);

...したがって、すべてのアイテムを文字列に変換してから、配列を割り当てる必要がありません。

問題

ただし、プログラミング全般の関数型スタイルのファンであり、特に C# でのメソッド チェーンのファンである私は、次のようなものを記述できるようにしたいと考えています。

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .string.Join(",");

ただし、これは正当な C# ではありません。はい、私はでそれを行うことEnumerable.Aggregateができました、そして、はい、私は独自の Join 拡張メソッドでそれを行うことができました )、しかし、これらのアプローチは読みにくい/非効率的であり、(それぞれ)警官のように感じるので、試してみたいと思いますそれは別の方法です。これまでに得た最も近いものは次のとおりです。

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .ApplyTo(
        Functional.Curry<string, IEnumerable<object>, string>
            (string.Join)(",")
    );

...次の拡張メソッドを使用:

public static class Functional
{
    public static TRslt
    ApplyTo<TArg, TRslt>(this TArg arg, Func<TArg, TRslt> func)
    {
        return func(arg);
    }

    public static Func<T1, Func<T2, TResult>>
    Curry<T1, T2, TResult>(this Func<T1, T2, TResult> func)
    {
        Func<Func<T1, T2, TResult>, Func<T1, Func<T2, TResult>>> curried
            = f => x => y => f(x, y);
        return curried(func);
    }
}

これは非常に冗長で、引数の 1 つを IEnumerable ではなく IEnumerable として定義しているため、パラメーターと戻り値の型を明示的に定義する必要があります。

チャレンジ

メソッド連鎖スタイルのプログラミングを使用して、これを達成するためのより適切な方法を見つけることができますか?

この課題は、C# で、複数のオーバーロードを持つ関数をカリー化するための簡潔な方法を見つけようとすることです。これはただの楽しみです。

4

3 に答える 3

6

どうしたの:

var list = string.Join(",",Enumerable.Range(1, 100).Where(i => i%2 == 0));

これが関数型プログラミングではない理由がよくわかりません。それは連鎖が少ないです、本当です。しかし、関数型プログラムは連鎖ではなく、より宣言的なステートメントを書くことであり、これは私の本で行っています。もちろん、本当に連鎖させたい場合は、これを行うことができます: 文字列配列を内破/結合するLINQの方法は何ですか?

于 2010-04-17T15:31:51.607 に答える
1

あなたの例から追加の Curry メソッドが必要な理由がわかりません。別の Lambda を使用するだけで、より簡潔なオプションが生成されます。

var list = Enumerable.Range(1, 100)
    .Where(i => i%2 == 0)
    .ApplyTo((x) => { return string.Join(",", x); })
于 2012-09-05T21:24:31.987 に答える
0

5年経っても答えが出ない、やってみよう!

効率的で、外部コードがなく、完全にチェーン化されており、読みやすい:

var list = Enumerable.Range(1, 100000)
    .Where(i => i % 2 == 0)
    .Aggregate(new StringBuilder(), (prev, i) => prev.AppendFormat(",{0}",i))
    .Remove(0,1)
    .ToString();
于 2015-06-28T21:10:07.507 に答える