获取特定标准的计数和平均值以及其余

时间:2016-12-27 11:37:29

标签: c# linq

我的数据格式如下..

    UserId    Property1      Property2     Property3   Testval
    1         1              1             10          35
    2         1              2             3           45
    3         2              5             6           55
and so on..

我有几个标准,下面是几个例子。

a) Where Property1=1 and Property3=10
b) Where Property1!=1 and Property2=5

我需要的是用户数和数量。那些属于这些标准的普通人,以及其他没有这些标准的人。

因此,结果数据结构如下..

User Count

Criteria         Users     
a                100
b                200
rest             1000

TestVal Average

Criteria         avg    
a                25
b                45
rest             15

我知道如何单独获取特定标准的用户列表。

data.Where(w=>w.Property1==1).Select(s=>s.UserId).ToList()

但是我如何获得usercount和avg val,更重要的是为其他用户提供相同的功能。

真心感谢任何帮助

由于

3 个答案:

答案 0 :(得分:4)

您似乎正在寻找按标准分组。像这样:

var result = data.GroupBy(x => 
    x.Property1 == 1 && x.Property3 == 10 ? 0 :
    x.Property1 != 1 && x.Property2 == 5 ? 1 :
    // ...
    -1)
    .Select(g => new
    {
        Criteria = g.Key,
        Users = g.Count(),
        Avg = g.Average(x => x.Testval),
    })
    .ToList();

答案 1 :(得分:2)

要获得特定标准的计数/平均值,这很容易

Func<MyUser, boolean> criterion1 = user => user.Property1==1;
var avg = data.Where(criterion1).Average(user => user.Testval);
var count = data.Where(criterion1).Count();

(这将枚举数据两次,所以如果这是一个问题,你可以在计算之前实现数据)

如果你想评估多个标准(并且不想像标准那样多次重复这段代码),你可以将它们放在字典中,并循环遍历它们:

 var criteria = new Dictionary<string, Func<MyUser, boolean>>{
    { "criterion1", user => user.Property1==1 },
    { "criterion2", user => user.Property1!=1 && user.Property2=5 },
    //...
 }

 foreach (var criterion in criteria){
   var avg = data.Where(criterion.Value).Average(user => user.Testval);
   var count = data.Where(criterion).Count();
   Console.WriteLine($"{criterion.Key} average: {avg}, count: {count}");
 }

您还可以将结果放在另一个字典中,例如

 var results = new Dictionary<string, Tuple<string, string>>();

 foreach (var criterion in criteria){
   var avg = data.Where(criterion.Value).Average(user => user.Testval);
   var count = data.Where(criterion).Count();
   results.Add(criterion.Key, Tuple.Create(avg, count));
 }

然后制作更好看的报告,或者您甚至可以创建一个更容易打印的特定结果类。

要获得其余的(不符合任何谓词的数据的计数/平均值),您可以循环遍历所有谓词,否定它们;

var query = data;
foreach (var criterion in criteria.Values){
  query = query.Where(user => !criterion(user));
}
var restAvg = query.Average(user => user.Testval);
var count = query.Count();

答案 2 :(得分:2)

您可以使用select new来返回包含您的条件的新的匿名类型对象。

public void Test()
    {
        var list = new List<User>();
        list.Add(new User {UserId = 1, Property1 = 1, Property2 = 1, Property3 = 10, Testval = 35});
        list.Add(new User {UserId = 1, Property1 = 2, Property2 = 2, Property3 = 3, Testval = 45});
        list.Add(new User {UserId = 1, Property1 = 5, Property2 = 5, Property3 = 6, Testval = 55});

        Func<User, bool> crit = u => u.Property1 == 1 & u.Property3==10;
        var zz = list.Where(crit)
            .GroupBy(t => new {ID = t.UserId})
            .Select(w => new
            {
                average = w.Average(a => a.Testval),
                count = w.Count(),
                rest = list.Except(list.Where(crit)).Average(a => a.Testval)
            }).Single();
    }