C#LINQ-如何申请分组?

时间:2009-12-01 20:01:02

标签: c# linq

我是linq的新手。从以下数据列表中,帮助我如何应用Group by和 其他构造以实现预期的输出,如下所示。

        List<SalesAnalysis> AnaList = new List<SalesAnalysis>();
        AnaList.Add(new SalesAnalysis("P001", 2009, 45000));
        AnaList.Add(new SalesAnalysis("P001", 2008, 13000));
        AnaList.Add(new SalesAnalysis("P002", 2009, 5000));
        AnaList.Add(new SalesAnalysis("P002", 2008, 15000));
        AnaList.Add(new SalesAnalysis("P003", 2009, 25000));
        AnaList.Add(new SalesAnalysis("P003", 2008, 65000));
        AnaList.Add(new SalesAnalysis("P004", 2009, 5000));
        AnaList.Add(new SalesAnalysis("P004", 2008, 3000));
        AnaList.Add(new SalesAnalysis("P004", 2007, 95000));
        AnaList.Add(new SalesAnalysis("P004", 2006, 83000));


   class SalesAnalysis
    {
        public string ProductCode
        {
            get;
            set;
        }

        public int Year
        {
            get;
            set;
        }

        public int NumberOfUnitsSold
        {
            get;
            set;
        }

        public SalesAnalysis(string productcode, int year, 
        int numberofunitssold)
        {
            ProductCode = productcode;
            Year = year;
            NumberOfUnitsSold = numberofunitssold;
        }

    }

条件:

1)仅报告2008和2009年的报告

2)Numberofunits&gt; = 30000是Top Movement产品

3)Numberofunits&gt; = 10000到&lt; 30000是平均运动产品

4)Numberofunits&lt; 10000是不良移动产品

预期产出:

Top Movement

Product Code  Year    Numberofunits
P003          2008    65000    
P001          2009    45000

Average Movement

Product Code  Year    Numberofunits
P003          2009    25000    
P002          2008    15000
P001          2008    13000

Poor Movement   

Product Code  Year    Numberofunits
P002          2009    5000  
P004          2009    5000
P004          2008    3000

4 个答案:

答案 0 :(得分:10)

要仅报告2008年和2009年的项目,请使用where子句:

where sa.Year == 2008 || sa.Year == 2009

对于其他人,我建议使用enum对“乐队”进行分类:

public enum Movement
{
    Top,
    Average,
    Poor
}

public static Movement MovementForAnalysis(SalesAnalysis sa)
{
    return sa.NumberOfUnitsSold >= 30000 ? Movement.Top
         : sa.NumberOfUnitsSold >= 10000 ? Movement.Average
         : Movement.Poor;
}

然后你可以这样做:

var query = from sa in AnaList
            where sa.Year == 2008 || sa.Year == 2009
            group sa by MovementForAnalysis(sa);

foreach (var group in query)
{
    Console.WriteLine("{0}: ", group.Key);
    foreach (var item in group)
    {
        Console.WriteLine("{0} / {1} / {2}", item.ProductCode, 
                          item.Year, item.NumberOfUnitsSold);
    }
    Console.WriteLine();
}

产生你所追求的输出,模数排序和格式化。

答案 1 :(得分:2)

Show(AnaList, 30000, int.MaxValue, "Top Movement");
Show(AnaList, 10000, 30000, "Average Movement");
Show(AnaList, 0, 10000, "Poor Movement");

static void Show(IEnumerable<SalesAnalysis> data, int min, int max, string caption)
{
    int[] years = {2008,2009};
    var qry = from row in data
               where years.Contains(row.Year)
                && row.NumberOfUnitsSold >= min
                && row.NumberOfUnitsSold < max
               orderby row.NumberOfUnitsSold descending
               select row;

    Console.WriteLine(caption);
    Console.WriteLine();
    Console.WriteLine("Product\tYear\tUnits");
    foreach(var row in qry) {
        Console.WriteLine("{0}\t{1}\t{2}",
            row.ProductCode, row.Year, row.NumberOfUnitsSold);
    }
}

答案 2 :(得分:2)

private enum Measure { Top, Average, Poor }

private Measure Classify(int nUnits)
{
   if      (nUnits >= 30000) return Measure.Top;
   else if (nUnits >= 10000) return Measure.Average;
   else return Measure.Poor;
}

/* ... */

var years = new int[] { 2008, 2009 };
var salesByMeasure =
    AnaList.Where(a => years.Contains(a.Year))
           .ToLookup(a => Classify(a.NumberOfUnitsSold));

var topSales = salesByMeasure[Measure.Top]; // e.g.

答案 3 :(得分:2)

尝试:

var groups = anaList.Where( p => p.Year > 2007 );  // limit year scope
                    .GroupBy( g => g.NumberOfUnitsSold > 30000
                                     ? "Top"
                                     : (g.NumberOfUnitSold >= 10000
                                          ? "Average"
                                          : "Poor" );

foreach (var group in groups)
{
    Console.WriteLine( "{0} Movement", group.Key );
    foreach (var product in group.OrderByDescending( p => p.NumberOfUnitsSold ))
    {
         Console.WriteLine( "{0} {1} {2}", product.ProductCode, product.Year, product.NumberofUnitsSold );
    }
}