2

我有一个以下类,我正在尝试使用我查询的一堆数据创建一个列表:

public class Agency
{
    public string AgencyName { get; set; }
    public int AgencyID { get; set; }
    public IEnumerable<AuditRule> rules { get; set; } 
}

其中“AuditRule”是:

public class AuditRule
{
    public int AuditRuleID { get; set; }
    public string AuditRuleName { get; set }
    public int AvgDaysWorked { get; set; }
}

现在,经过相当复杂的查询,我已经能够将我的数据放入一个匿名对象中,如下所示:

{ DateImported, AgencyID, AgencyName, AuditRuleName, AuditRuleID, DaysWorked }

我有数千条这种格式的记录,我正在尝试构建一个 IEnumerable <Agency>,它本身将包含每个机构的规则列表。

因此,以以下数据为例:

{ AgencyID = 1, AgencyName = "CCR", AuditRuleName = "Call", AuditRuleID = 1, DaysWorked = 3 }  
{ AgencyID = 1, AgencyName = "CCR", AuditRuleName = "Call", AuditRuleID = 1, DaysWorked = 5 }  
{ AgencyID = 1, AgencyName = "CCR", AuditRuleName = "Time", AuditRuleID = 2, DaysWorked = 2 }  
{ AgencyID = 2, AgencyName = "YRX", AuditRuleName = "Call", AuditRuleID = 1, DaysWorked = 3 }  
{ AgencyID = 2, AgencyName = "YRX", AuditRuleName = "Acct", AuditRuleID = 3, DaysWorked = 2 }

所以,从这些数据中,我首先尝试构建一个代理列表(顶部的类),对于这个例子来说,这显然是“CCR”和“YRX”。然后,对于每个机构,我希望在其 IEnumerable > 中为其每个规则都有一个条目,<AuditRule并且有记录。

因此,代理商“CCR”将有 2 个规则条目,“呼叫”和“时间”。“Call”AuditRule 条目的 AvgDaysWorked 为 4,因为我们正在平均机构“CCR”下的“Call”条目,即工作 3 天和 5 天。Time AuditRule 条目的 AvgDaysWorked 为 2,因为只有一个条目。

有一些 LINQ 忍者技能的人可以帮我将这些数据整理到每个机构的机构和规则列表中(以及为该规则/机构组合工作的平均天数)吗?

这对我来说已经足够复杂了,甚至能够将那个匿名对象放在一起,而且我真的很难编写这个查询来创建这个代理/审计规则列表。

这是我会使用 SelectMany() 或类似的东西的情况吗?我有点迷失在这里。

4

2 回答 2

9

我希望这能起到作用。

// GetAnonymousCollection() is hard to define... ;)
var anonymous = GetAnonymousCollection();

IEnumerable<Agency> result = anonymous
    .GroupBy(a => a.AgencyID)
    .Select(ag => new Agency()
    {
        AgencyID = ag.Key,
        AgencyName = ag.First().AgencyName,
        Rules = ag
            .GroupBy(agr => agr.AudiRuleID)
            .Select(agrg => new AuditRule()
            {
                AuditRuleID = agrg.Key,
                AuditRuleName = agrg.First().AuditRuleName,
                AvgDaysWorked = (Int32)agrg.Average(agrgr => agrgr.DaysWorked)
            })
      });

顺便说一句,考虑使用小数或浮点数来表示平均时间。

于 2009-07-02T18:56:48.643 回答
6

编辑:我认为我个人更喜欢 Daniel 的简单解决方案,尽管我的效率稍微高一些(因为它不需要通过调用First()来多次评估查询以获取代理/审计规则名称)。我不完全确定如何处理我的答案:它显示了一些不同的东西(按复合键分组),这很好,但同时它是一段笨重且笨拙的代码。再说一次,这是一个完整的例子,这使得它更容易玩......

想法,有人吗?我应该把它留在这里,还是删除它?


好的,我认为这可以满足您的要求。虽然它很邪恶。我没有时间立即解释它,但GroupBy方法是关键。

我已经对其进行了一些格式化,但它仍然不理想......

using System;
using System.Collections.Generic;
using System.Linq;

public class Agency
{
    public string AgencyName { get; set; }
    public int AgencyID { get; set; }
    public IEnumerable<AuditRule> Rules { get; set; } 

    public override string ToString()
    {
        return string.Format("Agency {0}/{1}:\r\n{2}",
            AgencyID, AgencyName,
            string.Concat(Rules.Select(x => x.ToString() + "\r\n")
                               .ToArray()));
    }
}

public class AuditRule
{
    public int AuditRuleID { get; set; }
    public string AuditRuleName { get; set; }
    public int AvgDaysWorked { get; set; }

    public override string ToString()
    {
        return string.Format("Audit rule {0}/{1}: {2}", AuditRuleID,
                             AuditRuleName, AvgDaysWorked);
    }
}

class Test
{    
    static void Main()
    {
        var previousQuery = new[]
        {
            new { AgencyID = 1, AgencyName = "CCR",
                  AuditRuleName = "Call",  AuditRuleID = 1, DaysWorked = 3 },
            new { AgencyID = 1, AgencyName = "CCR",
                  AuditRuleName = "Call", AuditRuleID = 1, DaysWorked = 5 },
            new { AgencyID = 1, AgencyName = "CCR",
                  AuditRuleName = "Time", AuditRuleID = 2, DaysWorked = 2 },
            new { AgencyID = 2, AgencyName = "YRX",
                  AuditRuleName = "Call", AuditRuleID = 1, DaysWorked = 3 },
            new { AgencyID = 2, AgencyName = "YRX",
                  AuditRuleName = "Acct", AuditRuleID = 3, DaysWorked = 2 },
        };

        var itemsGroupedByAgency = previousQuery.GroupBy
            (item => new { item.AgencyID, item.AgencyName });

        // Want to do the query for each group
        var query = itemsGroupedByAgency.Select
        // Outdented to avoid scrolling
        (group => new Agency 
         { 
             AgencyName = group.Key.AgencyName,
             AgencyID = group.Key.AgencyID,
             Rules = group.GroupBy(item => new { item.AuditRuleName, 
                                                 item.AuditRuleID },
                                                 (key, items) => new AuditRule
                    // Outdented to avoid scrolling :)
                    {
                       AuditRuleID = key.AuditRuleID,
                       AuditRuleName = key.AuditRuleName,
                       AvgDaysWorked = (int) items.Average(x => x.DaysWorked)
                    })
         });

        foreach (var item in query)
        {
            Console.WriteLine(item);
        }
    }
}
于 2009-07-02T19:04:29.517 回答