LINQ中的条件Groupby

时间:2014-05-27 16:12:04

标签: c# linq

我试图做非常相似的linq语句,但条件是条件略有不同。现在我只是用小修改重复整个陈述,但这应该更简洁。我所挣扎的是在语句中进行条件groupby和条件选择。我的长版本是:

class data
{
    public string year;
    public string quarter;
    public string month;
    public string week;
    public string tariff;
    public double volume;
    public double price;
}

class results
{
    public string product_code;
    public string tariff;
    public double volume;
    public double price;
}

class Program
{
    public static List<results> aggregationfunction(List<data> inputdata, string tarifftype, string timecategory)
    {
        List<results> returndata = new List<results>();

        if (tarifftype.Equals("daynight") & timecategory.Equals("yearly"))
        {
            returndata = inputdata.GroupBy(a => new { a.tariff, a.year })
                                  .Select(g => new results { product_code = g.Select(a => a.year).First(), tariff = g.Select(a => a.tariff).First(), volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
                                      .ToList();
        }
        else if (tarifftype.Equals("allday") & timecategory.Equals("yearly"))
        {
            returndata = inputdata.GroupBy(a => new { a.year })
                                  .Select(g => new results { product_code = g.Select(a => a.year).First(), tariff = "allday", volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
                                  .ToList();
        }
        else if (tarifftype.Equals("daynight") & timecategory.Equals("quarterly"))
        {
            returndata = = inputdata.GroupBy(a => new { a.tariff, a.year, a.quarter })
                                    .Select(g => new results { product_code = g.Select(a => a.year).First() + "_" + g.Select(a => a.quarter).First(), tariff = g.Select(a => a.tariff).First(), volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
                                    .ToList();
        }
        else if (tarifftype.Equals("allday") & timecategory.Equals("quarterly"))
        {
            returndata = inputdata.GroupBy(a => new { a.year, a.quarter })
                                  .Select(g => new results { product_code = g.Select(a => a.year).First() + "_" + g.Select(a => a.quarter).First(), tariff = "allday", volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
                                  .ToList();
        } 

        return returndata;
    }
}

任何指针都将不胜感激。正如你所看到的那样,关税和产品代码的分组和分配有所不同,但这并不意味着我需要重复一遍,是吗?

2 个答案:

答案 0 :(得分:6)

更短的代码:

return inputdata
    .GroupBy(a => new
    {
        a.year,
        quarter = timecategory == "quarterly" ? a.quarter : string.Empty,
        tariff = tarifftype == "daynight" ? a.tariff : "allday"
    })
    .Select(g => new results
    {
        product_code = g.Key.year + (string.IsNullOrEmpty(g.Key.quarter) ? "" : "_" + g.Key.quarter),
        tariff = g.Key.tariff,
        volume = g.Sum(a => a.volume),
        price = g.Average(a => a.price)
    })
    .ToList();

答案 1 :(得分:1)

inputdata.GroupBy返回的IGrouping<TKey, data>项(其中datainputdata的元素类型)将始终实现IEnumerable<data>,无论匿名密钥类型如何(可能是{year}或{tariff,year}等)。因此,所有GroupBy值都可以推广到IEnumerable<IEnumerable<data>>,然后您可以将其分解为两个步骤:

IEnumerable<IEnumerable<data>> groups;
if (condition) {
    groups = inputdata.GroupBy(a => new { a.year });
} else if (condition) {
    groups = inputdata.GroupBy(a => new { a.tariff, a.year });
} else {
    groups = inputdata.GroupBy(a => new { a.year, a.quarter });
}
returndata = groups.Select(...)

条件选择应该更容易实现,因为您可以只使用conditional operators内联,或将选择器函数扩展为多行块,例如:

.Select(g => {
    var product_code = ...;
    if (condition) {
        product_code += "_" + ...;
    }
    return new results { product_code = product_code, ... };
})