【问题标题】:Add property dynamically to Linq's GroupBy result将属性动态添加到 Linq 的 GroupBy 结果
【发布时间】:2018-07-17 12:21:06
【问题描述】:

我有两个班级,CustomerKPI

public class Customer : BaseModel
{
    public String Code { get; set; }
    ...
    public List<KPI> KPIs { get; set; }
}

public class KPI : BaseModel
{
    public String Name { get; set; }
    public int PersonalValue { get; set; }
    public int RegionalValue { get; set; }
    public int NationalValue { get; set; }
    public String Group { get; set; }
}

我需要按Group 属性对 KPI 进行分组,这样如果我的数据如下所示:

+---------------------------------+
| Name PValue RValue NValue Group |
+---------------------------------+
| Low    100    600    300    Car  |
| High   900    400    700    Car  |
| Low    200    300    500   Truck |
| High   800    700    500   Truck |
+---------------------------------+

在对项目进行分组后,我需要一些额外的属性:

Names: 'Low, High' PValuePercentages: '10, 90' RValuePercentages: '60, 40' NValuePercentages: '30, 70'

这基本上是逗号分隔的字符串,其中包含从分组项中计算出来的值。我需要将它们格式化,以便我可以使用 Razor 轻松地将它们插入 HTML 元素。

这正是我目前在 Razor 中所做的,但在 .cs 文件中进行了更简单的测试和调试:

foreach (var customer in customerList)
{
    var groups = customer.KPIs.GroupBy(item => item.Group);

    foreach (var group in groups)
    {
        var groupName = group.Key ?? "OTHERS";

        foreach (var kpi in group)
        {
            var kpiName = kpi.Name;
            var personalValue = kpi.PersonalValue;
            var regionalValue = kpi.RegionalValue;
            var nationalValue = kpi.NationalValue;
        }

        if(!String.IsNullOrEmpty(group.Key))
        {
            // This doesn't work yet
            //var acuVal1 = group.AcuVal1;
            //var acuVal2 = group.AcuVal2;
            //var acuVal3 = group.AcuVal3;


            foreach (var kpi in group)
            {
                var kpiName= kpi.Name;   
            }
        }
    }
}

如果我尝试通过 Linq 查询将组更改为

var groups = customer.KPIs.GroupBy(item => item.Group).
                    Select(item => new
                    {
                        item.Key,
                        item,
                        AcuVal1 = item.Sum(i => i.PersonalValue),
                        AcuVal2 = item.Sum(i => i.RegionalValue),
                        AcuVal3 = item.Sum(i => i.NationalValue)
                    }).ToList();

注意:Sum() 在这种情况下不是我需要的,但出于测试目的,它可以工作并保持简单。

做完这些后,线条

foreach (var kpi in grupo)

给出以下错误:

foreach 语句不能对 '' 因为'' 不包含“GetEnumerator”的公共定义

我做错了什么?

【问题讨论】:

  • @mjwills 我想我已经做到了,当我显示样本数据的特定值时,我的分组项目应该如何基于它们计算。我还能添加什么来使问题更清楚?
  • 我认为问题应该更多地体现在:我是否清楚地解释了我的问题并给出了具体的例子来帮助理解我想要完成的事情?我想我做到了。不,您不能将我的代码 sn-ps 复制并粘贴到 IDE 中并对其进行处理,但是对于 Stack 上的大多数问题,您不能这样做。我相信你可以很容易地理解我的问题是什么,如果拥有知识(我没有,所以在这里问),帮助我解决它。
  • GroupBy 为您提供每个组的元素(以及密钥)。您所需要的只是将Select所需的信息转换成匿名类型。
  • 可能正确的解决方案是使用 DataTable。请参阅:aspsnippets.com/Articles/…
  • @IvanStoev 我已经更新了这个问题,希望能更好地解释我的代码问题。我已经尝试按照您说的做,但无法正常工作。

标签: c# asp.net .net linq razor


【解决方案1】:

当你 group by 进入 item 时,item 是一个键值的 IGrouping,而 groups 只是一个集合具有 key 属性和一些聚合属性以及 item 属性的匿名类型。

考虑到这一切,如果你想迭代一个分组的子集合,你需要迭代一个组的 .item 属性

var groups = from kpi in kpis
            group kpi by kpi.Group into item
            select new
            {
                item.Key,
                item,
                AcuVal1 = item.Sum(i => i.PersonalValue),
                AcuVal2 = item.Sum(i => i.RegionalValue),
                AcuVal3 = item.Sum(i => i.NationalValue)
            };

foreach (var group in groups)
{
    foreach (var kpi in group.item)
    {
        var kpiName = kpi.Name;
    }
}

注意:我很确定您实际上并不需要嵌套的 foreach,并且您应该能够通过结果查询扩展组来实现您想要的结果

var groups = from kpi in kpis
            group kpi by kpi.Group into groupings
            let names = groupings.Select(p => p.Name)
            let pvalues = groupings.Select(p => p.PersonalValue)
            let rvalues = groupings.Select(p => p.RegionalValue)
            let nvalues = groupings.Select(p => p.NationalValue)
            select new
            {
                Key = groupings.Key,
                Names = string.Join(", ", names),
                PValues = string.Join(", ", pvalues),
                RValues = string.Join(", ", rvalues),
                NValues = string.Join(", ", nvalues),
            };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-20
    • 2019-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多