问题描述
我有一个带有询问答案的应用程序(50个字段,具有upa1,upa2,upd1,upd6等的名称,具有可能的值" y"," n"和" na").
我可以得到并计数一个字段:
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> }
这应该快速运行.
其他推荐答案
假设您有这样的课程:
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" }, };
我们可以创建另一个可以保存我们的密钥和总价值的类.这样的东西:
[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; } }
我们可以比实例化关键值的字典,其中关键将是您的查询答案,而值将是我们的询问类的一个实例.
var summary = new Dictionary<string, 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诉讼相比.否则,我们将创建一个新的询问对象,并将其交给他.每次我们返回案例字典中的种子.
问题描述
I have an app with an inquiry answers (50 fields, with names like upa1, upa2, upd1, upd6, etc, with possible values "y", "n" and "na").
I can get and count one single field with this:
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> }
And it will output this:
These are the totals for upa1: y : 30 n : 11 na : 18
I can repeat this for all questions manually, but I need to count the number of "y", "n" and "na" for all questions to form this single output:
These are the totals for all questions: y : 1342 n : 879 na : 445
I know there are already hundreds of topics about these issues, but the information is far too stretched and over way too many variations on this matter (different tables, joins, etc). Nothin on the "sum count over multiple fields".
Thanks.
Also, on a side note, each line only appears if the answer exists at least once, but I need it to show even if it is a "y : 0". Is this possible?
推荐答案
With only three possible answers you can do this in three separate queries:
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> }
This should run reasonably fast.
其他推荐答案
Lets say you have a class like this:
public class Inquiry { public string UpaName { get; set; } public string UpaValue { get; set; } }
Now lets populate that list with some test data:
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" }, };
We can create another class that would hold our key along with sumarized values. Something like this:
[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; } }
We could than instantiate a dictionary of key values where key would be your inquiry answer and the value would be an instance of our InquirySummary class.
var summary = new Dictionary<string, InquirySummary>();
We would than define an action that would take INquiry object and InquirySummary object and would summarize the values.
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; });
Finally you would have all the neccessary things to call an aggregate that would run only once through your list.
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; });
This would basically give our dictionary as seed and than we would start looping through the list. First if condition would check if the key already exists in the dicitonary and than would simpy call the sumarize action on that value. Otherwise we would create a new InquirySummary object and would sumarize into him. Each time we are returning the seed which is in our case dictionary.