حساب المتوسط المرجح مع LINQ
-
01-10-2019 - |
سؤال
هدفي هو الحصول على متوسط مرجح من جدول واحد ، على أساس آخر الجداول المفتاح الأساسي.
البيانات المثال:
جدول1
Key WEIGHTED_AVERAGE
0200 0
Table2
ForeignKey Length Value
0200 105 52
0200 105 60
0200 105 54
0200 105 -1
0200 47 55
أنا بحاجة للحصول على متوسط مرجح على أساس طول قطعة و لا تحتاج إلى تجاهل قيم -1.أنا أعرف كيفية القيام بذلك في SQL, ولكن هدفي هو أن تفعل هذا في LINQ.يبدو شيئا من هذا القبيل في SQL:
SELECT Sum(t2.Value*t2.Length)/Sum(t2.Length) AS WEIGHTED_AVERAGE
FROM Table1 t1, Table2 t2
WHERE t2.Value <> -1
AND t2.ForeignKey = t1.Key;
أنا لا تزال جديدة جدا أن LINQ, وجود صعوبة في معرفة كيف سيترجم هذا.نتيجة المتوسط المرجح أن يخرج إلى حوالي 55.3.شكرا لك.
المحلول
أنا أفعل هذا يكفي أنني خلقت امتداد طريقة LINQ.
public static double WeightedAverage<T>(this IEnumerable<T> records, Func<T, double> value, Func<T, double> weight)
{
double weightedValueSum = records.Sum(x => value(x) * weight(x));
double weightSum = records.Sum(x => weight(x));
if (weightSum != 0)
return weightedValueSum / weightSum;
else
throw new DivideByZeroException("Your message here");
}
بعد حصولك على مجموعة فرعية من بيانات الإتصال يبدو مثل هذا.
double weightedAverage = records.WeightedAverage(x => x.Value, x => x.Length);
أصبح هذا مفيد للغاية لأنه يمكن الحصول على متوسط مرجح من أي مجموعة من البيانات استنادا إلى حقل آخر في نفس السجل.
التحديث
أنا الآن التحقق من قسمة صفر ورمي أكثر تفصيلا استثناء بدلا من العودة 0.تتيح للمستخدم التقاط استثناء والتعامل معها حسب الحاجة.
نصائح أخرى
إذا كنت على يقين من أن لكل الأجنبية الرئيسية في Table2 هناك سجل المقابلة في جدول1 ثم يمكنك تجنب الانضمام إلى جعل مجرد الفريق من قبل.
في هذه الحالة ، LINQ الاستعلام مثل هذا:
IEnumerable<int> wheighted_averages =
from record in Table2
where record.PCR != -1
group record by record.ForeignKey into bucket
select bucket.Sum(record => record.PCR * record.Length) /
bucket.Sum(record => record.Length);
التحديث
هذا كيف يمكنك الحصول على wheighted_average
معين foreign_key
.
IEnumerable<Record> records =
(from record in Table2
where record.ForeignKey == foreign_key
where record.PCR != -1
select record).ToList();
int wheighted_average = records.Sum(record => record.PCR * record.Length) /
records.Sum(record => record.Length);
على ToList طريقة تسمى عند جلب السجلات هو تجنب تنفيذ الاستعلام مرتين في حين تجميع السجلات في منفصلين مجموع العمليات.
(الرد على jsmith تعليق على الجواب أعلاه)
إذا كنت لا ترغب في دورة من خلال بعض جمع يمكنك محاولة ما يلي:
var filteredList = Table2.Where(x => x.PCR != -1)
.Join(Table1, x => x.ForeignKey, y => y.Key, (x, y) => new { x.PCR, x.Length });
int weightedAvg = filteredList.Sum(x => x.PCR * x.Length)
/ filteredList.Sum(x => x.Length);