1
return new SchoolFees(
        new Percentage(schoolFeesResult.Sum(x => (x.Amount.Value / totalFees) * x.TuitionFee.Value)),
        new Percentage(schoolFeesResult.Sum(x => (x.Amount.Value / totalFees) * x.TravellingFee.Value)),
        new Percentage(schoolFeesResult.Sum(x => (x.Amount.Value / totalFees) * x.ResidentialFee.Value)));

一度操作してschoolFeesResult、さまざまな種類の料金 ( TuitionTravellingResidence) のそれぞれの加重平均を計算する方法はありますか。(x.Amount.Value / totalFees)基本的に、コードに 3 回表示したくないですか?

4

4 に答える 4

3

You could use something like this:

var fees = from fee in schoolFeesResult
           let weight = fee.Amount.Value / totalFees
           select new 
           {
               TuitionFee = weight * fee.TuitionFee.Value,
               TravellingFee = weight * fee.TravellingFee.Value,
               ResidentialFee = weight * fee.ResidentialFee.Value
           };

// if the calculation of the fees is a performance bottleneck,
// uncomment the next line:
// fees = fees.ToList();

return new SchoolFees(
    new Percentage(fees.Sum(x => x.TuitionFee),
    new Percentage(fees.Sum(x => x.TravellingFee),
    new Percentage(fees.Sum(x => x.ResidentialFee));

You could go even further:

var fees = (from fee in schoolFeesResult
            let weight = fee.Amount.Value / totalFees
            group fee by 1 into g
            select new 
            {
                TuitionFee = g.Sum(x => weight * x.TuitionFee.Value),
                TravellingFee = g.Sum(x => weight * x.TravellingFee.Value),
                ResidentialFee = g.Sum(x => weight * x.ResidentialFee.Value)
            }).Single();

return new SchoolFees(
    new Percentage(fees.TuitionFee,
    new Percentage(fees.TravellingFee,
    new Percentage(fees.ResidentialFee);

But I doubt that this second version is a good idea. It makes the code hard to understand. I added it purely for academic reasons, to show what is possible.

于 2013-01-22T12:44:01.137 に答える
2

もう 1 つの脳を壊すソリューション

Func<Func<Fee, decimal>, decimal> totalFee = feeSelector =>
   schoolFeesResult.Sum(x => x.Amount.Value / totalFees * feeSelector(x));

return new SchoolFees(
   new Percentage(totalFee(f => f.TuitionFee.Value)),
   new Percentage(totalFee(f => f.TravellingFee.Value)),
   new Percentage(totalFee(f => f.ResidentialFee.Value))
);

またはさらに短い:

Func<Func<Fee, decimal>, Percentage> percentageOf = feeSelector =>
   new Percentage(schoolFeesResult.Sum(x => 
         x.Amount.Value / totalFees * feeSelector(x)));

return new SchoolFees(
   percentageOf(f => f.TuitionFee.Value),
   percentageOf(f => f.TravellingFee.Value),
   percentageOf(f => f.ResidentialFee.Value)
);
于 2013-01-22T13:16:17.303 に答える
1

私はあなたがそれを別のクエリに入れることができると思います、私見それはそれよりももっと赤くなります:

var percentages = schoolFeesResult
    .Select(x => new { SFR = x, AmoundDivFees = (x.Amount.Value / totalFees)})
    .Select(x => new { 
        TuitionFee = x.AmoundDivFees * x.SFR.TuitionFee.Value,
        TravellingFee = x.AmoundDivFees * x.SFR.TravellingFee.Value,
        ResidentialFee = x.AmoundDivFees * x.SFR.ResidentialFee.Value
    });
return new SchoolFees(
    new Percentage(percentages.Sum(x => x.TuitionFee)),
    new Percentage(percentages.Sum(x => x.TravellingFee)),
    new Percentage(percentages.Sum(x => x.ResidentialFee)));

もちろん、私はそれをテストすることができませんでした。

于 2013-01-22T12:37:52.573 に答える
1

私はこの実装をWeightedAverage拡張メソッドとして使用しますIEnumerable<T>

public static double? WeightedAverage<TSource>(this IEnumerable<TSource> source
                                                       , Func<TSource, float> weightField
                                                       , Func<TSource, double> propertyToWeight)
{
    var total = source.Sum(weightField);

    var sum = source.Select(item => weightField(item) * propertyToWeight(item)).Sum();
    return sum / total;

}  

もちろんsingle、対処すべき過負荷がいくつかありますsingle?doubleおそらく、これを調整して、達成しようとしていることに合わせることができます。

于 2013-01-22T12:35:01.753 に答える