web-dev-qa-db-ja.com

ラムダ式を「許可」する方法は?

このlinqクエリをラムダ式でEntityに書き換えるにはどうすればよいですか?
ラムダ式でletキーワードまたは同等のものを使用したい。

var results = from store in Stores
              let AveragePrice =  store.Sales.Average(s => s.Price)
              where AveragePrice < 500 && AveragePrice > 250

私の質問の下でコメントされているもののようないくつかの同様の質問については、

.Select(store=> new { AveragePrice = store.Sales.Average(s => s.Price), store})

これは、各アイテムのAveragePriceを計算しますが、前述のクエリスタイルでは、let式は、平均を何度も計算することを防ぎます。

39
Reza Owliaei

したがって、拡張メソッドの構文を使用できます。これには、現在使用しているよりも1つのラムダ式が含まれます。 letはありません。複数行のラムダを使用して変数を宣言するだけです:

var results = Stores.Where(store => 
{
    var averagePrice = store.Sales.Average(s => s.Price);
    return averagePrice > 250 && averagePrice < 500;
});

平均価格の比較を変更したことに注意してください。なぜなら、あなたの結果は決して結果を返さないからです(500を超え250未満)。

代替手段は

var results = Stores.Select(store => new { Store = store, AveragePrice = store.Sales.Average(s => s.Price})
    .Where(x => x.AveragePrice > 250 && x.AveragePrice < 500)
    .Select(x => x.Store);
46
Jay

基本的に、Selectと匿名型を使用してオブジェクトに平均を追加し、その後に残りのステートメントを追加する必要があります。

テストされていませんが、次のようになります。

Stores.Select(
x => new { averagePrice = x.Sales.Average(s => s.Price), store = x})
.Where(y => y.averagePrice > 500 && y.averagePrice < 250)
.Select(x => x.store);

警告、これらの構造には注意してください。 letを使用すると、コレクション内のオブジェクトごとに新しい匿名型が作成され、大きなコレクションでは多くのメモリが消費されます...

詳細についてはこちらをご覧ください: 連鎖拡張メソッドに入れます

24
Yoeri

別のオプションは、この拡張メソッドを定義することです:

public static class Functional
{
    public static TResult Pipe<T, TResult>(this T value, Func<T, TResult> func)
    {
        return func(value);
    }
}    

次に、次のようにクエリを記述します。

var results = Stores
    .Where(store => store.Sales.Average(s => s.Price)
        .Pipe(averagePrice => averagePrice < 500 && averagePrice > 250));
4
Timothy Shields