Linq - 分组和多个字段的计数(输出总数)
我有一个查询答案的应用程序(50个字段,名称为upa1,upa2,upd1,upd6等,可能的值为“y”, “n”和“na”)。Linq - 分组和多个字段的计数(输出总数)
我可以和计数这一个单场:
foreach(var y in items.GroupBy(g => g.upa1)
.Select(group => new {upa1name = group.Key, upa1count = group.Count()})) {
<div>These are the totals for upa1:</div>
<div>@y.upa1name : @y.upa1count</div>
}
,它会输出这样的:
These are the totals for upa1:
y : 30
n : 11
na : 18
我可以重复这个手动的所有问题,但我需要算所有问题的“y”,“n”和“na”数量形成单个输出:
These are the totals for all questions:
y : 1342
n : 879
na : 445
我知道那里已经有数百个关于这些问题的主题,但是信息太过紧张,并且在这个问题上有太多变化(不同的表格,连接等)。没有关于“多个领域的总数”。
谢谢。
此外,在附注中,每条线只在答案至少存在一次时才会出现,但即使它是“y:0”,我也需要它显示。这可能吗?
只有三个可能的答案,你可以在三个不同的查询做到这一点:
foreach (var ans in new[] {"y", "n", "na"}) {
var count = items.Sum(item =>
(item.upa1==ans?1:0) + (item.upa2==ans?1:0) + (item.upd1==ans?1:0) + ...
);
<div>These are the totals for @ans:</div>
<div>@ans : @count</div>
}
这应该运行相当快。
看起来很简单,但它意味着使用自定义控制器。由于我没有真正涉足2sxc自定义API设计的东西,所以只能查看解决方案。 –
@JoãoGomes只要您将所有名称放在比较链中而不是上面的'...'中,这种方法就可以工作。 – dasblinkenlight
太好了。简单,容易,可以理解。喜欢这个解决方案。谢谢。 –
比方说你有一个这样的类:
public class Inquiry
{
public string UpaName { get; set; }
public string UpaValue { get; set; }
}
现在让我们来填充该列表与一些测试数据:
var list = new List<Inquiry>()
{
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
new Inquiry() { UpaName = "upa1", UpaValue = "n" },
new Inquiry() { UpaName = "upa1", UpaValue = "na" },
new Inquiry() { UpaName = "upa2", UpaValue = "y" },
new Inquiry() { UpaName = "upa2", UpaValue = "n" },
new Inquiry() { UpaName = "upa2", UpaValue = "na" },
new Inquiry() { UpaName = "upa2", UpaValue = "na" },
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
new Inquiry() { UpaName = "upa2", UpaValue = "n" },
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
new Inquiry() { UpaName = "upa1", UpaValue = "y" },
};
我们可以创建另一个类,将持有我们的关键随着sumarized值。事情是这样的:
[DebuggerDisplay("{UpaName,nq} y:{y,nq} n:{n,nq} na:{na,nq}")]//include Sysytem.Diagnostics
public class InquirySummary
{
public string UpaName { get; set; }
public int y { get; set; }
public int n { get; set; }
public int na { get; set; }
}
我们可以比实例键值的字典,其中关键是你查询的答案和值将是我们InquirySummary类的一个实例。
var summary = new Dictionary<string, InquirySummary>();
我们将定义一个操作,该操作将获取INquiry对象和InquirySummary对象并将总结值。
Action<Inquiry, InquirySummary> sumarize = new Action<Inquiry, InquirySummary>((i, sum) =>
{
if (i.UpaValue == "y")
sum.y += 1;
else if (i.UpaValue == "n")
sum.n += 1;
else
sum.na += 1;
});
最后,您将拥有所有需要的东西来调用一个只能在列表中运行一次的聚合。
list.Aggregate(summary, (b, c) =>
{
if (summary.ContainsKey(c.UpaName)) {
var sum = summary[c.UpaName];
sumarize(c, sum);
}
else
{
var sum = new InquirySummary();
summary.Add(c.UpaName, sum);
sumarize(c, sum);
}
return summary;
});
这基本上将我们的字典作为种子,并且比我们开始循环遍历列表。首先如果条件将检查密钥是否已经存在于dicitonary中,并且会简单地将该sumarize动作称为该值。否则,我们会创建一个新的InquirySummary对象,并将他咀嚼。每次我们返回我们的案例词典中的种子。
这离我的理解还有几十年。它将需要控制器的自定义API。更简单的视图解决方案将是首选。 –
不需要自定义API。把它放在扩展方法中,然后在你的视图中调用它。 – Rob
现在改变它可能有点晚,但更好的数据模型会为你解决这个问题。问题不应该在单独的领域,而应该包含在一系列问题中,每个问题都有一个名称,内容和一系列答案。 – oerkelens
一点也不迟。我可以尝试使用问卷ID,问题,答案等优化格式制作表格。因此,每个问卷将在表中放置50+行,如“1088”,“upa1”,“y”和“1088”,“upa2”,“n”等。 –
或其他任何格式,如果您可以给我例。 –