我有一个Linq查询,我在其中获得一组问题的响应值。我按问题对响应数据进行分组,然后对响应数据执行各种聚合,例如对它们求平均值。我还根据指定响应选项值范围,计算可归类为“高”,“中”和“低”的响应比例。
var result = ItemResponses
.Where (ir => ir.ItemID < 4 && ir.AssessmentInstance.ProjectID == 5)
.Select (ir => ir)
.GroupBy (ir => new {
ir.ItemID
}).Select (grouped => new {
ItemID = grouped.Key.ItemID,
Average = (double)grouped.Average (g => g.OptionValue),
ProportionHighScore =
(double)grouped.Where(g => g.OptionValue == 5 || g.OptionValue == 6).Count()
/ (double)grouped.Count(),
});
我想移动代码,我指定哪些选项值应该组合成一个远离Linq查询的“高”响应类别,并且正在考虑设置一个扩展方法来执行此操作。在扩展方法中,我可以指定响应选项值的不同组合,我可以将其评分为“高”分数,跨越风格(例如,如果最大响应不是6但是10,那么我会计算选项8,9, 10,朝着“高”回应类别。
扩展方法可能如下所示:
public static double ProportionHighScore(this IGrouping<a,b> values, int ResponseOptionID)
{
double ret = 0;
switch (ResponseOptionID)
{
case 1:
//code here to combine response options 5 and 6, and divide by total
break;
case 2:
//code here to combine response options 8, 9 and 10 and divide by total
break;
case 3:
//etc..
break;
default:
break;
}
return ret;
}
但我的问题是:如何将Linq分组值作为参数传递给扩展方法? IGrouping b的类型是匿名类型。
更新
我喜欢只做GroupBy (ir => it.ItemID)
的想法,以便我可以访问"IGrouping<int, ItemResponse>"
。但在这里的代码我简化了一点。在我的实际代码中还有一些事情正在发生,例如,如果项目被标记为“IsReversed
”,则反转OptionValue分数。
var result2 = ItemResponses
.Where (ir => ir.ItemID < 4 && ir.AssessmentInstance.ProjectID == 5)
.Select (ir => new {
ItemID = ir.ItemID,
OptionValue =
(
//Reverse option value of items that are flagged to require reverse scoring
ir.Item.IsReversed == 0 ? ir.OptionValue :
((ir.ResponseScaleOption.ResponseScale.MaxValue + 1) - ir.OptionValue)
),
})
.GroupBy (g => new {g.ItemID})
.Select (grouped => new {
ItemID = grouped.Key.ItemID,
Average = (double)grouped.Average (g => g.OptionValue),
ProportionHighScore =
(double)grouped.Where(g => g.OptionValue == 5 || g.OptionValue == 6).Count()
/ (double)grouped.Count(),
});
在此查询的某些版本中,我还包括来自某些连接表的字段。所以需要反转OptionValues是我认为我需要一个匿名类型的原因之一。也许我需要创建一个可以投影到的新类(“ItemResponseForAggregation
”或某个此类名称),然后能够为我的扩展参数执行IGrouping<int, ItemResponseForAggregation>
?
答案 0 :(得分:1)
您无法以这种方式传递匿名类型。他们必须处于直接执行环境中,以便将它们视为强类型。创建一个轻量级类型,以便您可以将其传入,然后在参数&#39; b&#39;上添加参数约束。强制它必须是你已经创建的类型。
答案 1 :(得分:0)
我在LINQPad中模拟了你正在寻找的想法(如果我正确理解要求):
void Main()
{
var ItemResponses = new List<ItemResponse>();
var result = ItemResponses
.Where(ir => ir.ItemID < 4 && ir.AssessmentInstance.ProjectID == 5)
.GroupBy(ir => ir.ItemID)
.Select(
grouped => new {
ItemID = grouped.Key,
Average = (double)grouped.Average(g => g.OptionValue),
ProportionHighScore = grouped.ProportionHighScore(1, 2, 3, 4, 5)
}
);
result.Dump();
}
public class ItemResponse
{
public int ItemID { get; set; }
public int OptionValue { get; set; }
public AssessmentInstanceItem AssessmentInstance { get; set; }
}
public class AssessmentInstanceItem
{
public int ProjectID { get; set; }
}
public static class ItemResponseExtensions
{
public static double ProportionHighScore(this IGrouping<int, ItemResponse> values, params int[] ResponseOptionID)
{
double count = 0;
double total = values.Count();
foreach (int r in ResponseOptionID)
count += (double)values.Where(g => g.OptionValue == r).Count();
return count / total;
}
}
在扩展方法中,params
参数允许您根据需要指定任意数量的选项。然后我只是循环选项,为每个响应选项添加计数。