带类型转换的LINQ中的Conditional Group和Select

本文关键字:Group Select Conditional 中的 类型转换 LINQ | 更新日期: 2023-09-27 18:27:50

我知道这方面已经有很多问题了,但由于类型转换(我认为),我仍然无法让它发挥作用。

我有一个自定义类的列表,我通常根据用户的选择按月份(mt)或季度(qr)对其进行分组。这很好用。然而,现在我有请求允许在2013年第4季度和2013年剩余时间进行分组。Mt和Qr是字符串。如果只有第四季度在季度,其余月份在月份,则四分之一是双倍的,等于4。

这是我所拥有的:

List<MyClass> results = classlist
  .GroupBy(a => new { 
                a.rg,
                a.tar,
                a.mt = ((double.Parse(a.qr) < quartpos) ? a.mt : 0),
                a.qr })
  .Select(g => new MyClass { 
               RG = g.Select(a => a.rg).First(),
               tar = g.Select(a => a.tar).First(),
               yr = g.Select(a => a.yr).First(),
               qr = g.Select(a => a.qr).First(),
               mt = g.Select(a => a.mt).First(),
               pp = g.Average(a => double.Parse(a.pp)),
               pi = g.Sum(a => double.Parse(a.pi)),
               cp = g.Average(a => double.Parse(a.cp)),
               ci = g.Sum(a => double.Parse(a.ci)),
               it = g.Sum(a => double.Parse(a.it)),
               to = g.Sum(a => double.Parse(a.to)),
               cnt = g.Select(a => a.dt).Distinct().Count(),
               pdvol = g.Sum(a => (double.Parse(a.pp) <= 1) 
                                  ? 0 
                                  : (double.Parse(a.pi) / double.Parse(a.pp))) })
  .ToList();

这会引发两个错误:

  1. String Int类型转换-因为mt是字符串,但:0是Int

  2. 无效的匿名类型成员声明。

我完全知道,我必须在select中使用相同的语法,以确保如果按季度分组,则选择季度,如果按mounths分组,则也选择月份。

类别定义:

public class Myclass
{
    public string yr;
    public string qr;
    public string mt;
    public string cw;
    public string tar;
    public string RG;
    public double pp;
    public double pi;
    public double cp;
    public double ci;
    public double it;
    public double to;
    public double pd;
    public double cd;
    public double fp;
    public double fi;
    public double fd;
    public int cnt;
    public double pdmw;
    public double pdvol;
}

classlist是一个所有变量都是字符串的类,直接从csv导入。

我的问题是如何有条件地对月份(mt)进行分组?

带类型转换的LINQ中的Conditional Group和Select

a.mt = ((double.Parse(a.qr) < quartpos) ? a.mt : 0)

你不能创建这样的匿名类型。看看文档中的语法。

你想要:

a.mt

PropertyName = ((double.Parse(a.qr) < quartpos) ? a.mt : 0)

在这一行。

我能想到的一个不太优雅的解决方案是用一个简单的.select(a => double.Parse(a.qr) < quartpos)classlist拆分为两个新列表,然后保留执行上面所有其他操作的代码,并按月份和季度对list1和list2进行分组。这将消除对条件分组的需要。

但我想一定有更好的办法。

        public static IEnumerable<EVFile> SmallerQ(this IEnumerable<EVFile> @this, double quarterpos)
    {
        return from ev in @this
               where (double.Parse(ev.qr)<quarterpos)
               select ev;
    }
    public static IEnumerable<EVFile> LargerEqQ(this IEnumerable<EVFile> @this, double quarterpos)
    {
        return from ev in @this
               where (double.Parse(ev.qr) >= quarterpos)
               select ev;
    }
newlist =  classlist.SmallerQ(quarterpos).ToList();

使用这两种扩展方法,我可以将原始列表一分为二,然后在不使用条件组联接的情况下继续操作。因此,它确实起到了作用,但正如所说的,效果不太好。