简体   繁体   English

C#LINQ-如何申请分组?

[英]C# LINQ -How to apply group by?

I am new to linq.From the list of following data,help me how can i apply Group by and other construct to achieve the expected output as given below. 我是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;
        }

    }

conditions : 条件 :

1) Report only needed for the year 2008 and 2009 only 1)仅报告2008年和2009年的报告

2) Numberofunits >=30000 are Top Movement products 2)Numberofunits> = 30000是Top Movement产品

3) Numberofunits >=10000 to < 30000 are average movement products 3)Numberofunits = = 10000至<30000是平均运动产品

4) Numberofunits <10000 are poor moving product 4)Numberofunits <10000是移动产品差

Expected output: 预期产量:

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

To report only items for 2008 and 2009, use a where clause: 要仅报告2008年和2009年的项目,请使用where子句:

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

For the rest, I would suggest an enum to classify the "band": 对于其他人,我建议使用枚举来对“乐队”进行分类:

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;
}

You can then do: 然后你可以这样做:

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();
}

That produces the output you were after, modulo ordering and formatting. 这会产生你所追求的输出,模数排序和格式化。

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);
    }
}
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.

Try: 尝试:

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 );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM