1

请允许我先向您展示我的残暴逻辑:

public void MergeLotDataList(List<SPCMeasureData> sPCMeasureDataList)
        {
            double standMaxTotal = 0.0;
            double standAimTotal = 0.0;
            double standMinTotal = 0.0;
            List<SPCLotData> lotDataRemovalList = new List<SPCLotData>();
            foreach (SPCLotData lotData in sPCLotDataList)
            {
                //Find if there's any lotDatas with duplicate identify strings
                var duplicateLotList = sPCLotDataList.Where(w => w.GetIdentifyString() == lotData.GetIdentifyString()).Select(s=>s);
                int duplicateLotCount = duplicateLotList.Count();
                if (duplicateLotCount <= 1)
                    continue;

                //Get the standMax,standAim,standMin total for computing average later
                //and remove duplicates, leaving only a single unique lotData
                foreach (SPCLotData lotData_inner in duplicateLotList)
                {
                    standMaxTotal += lotData_inner.GetStandMax();
                    standAimTotal += lotData_inner.GetStandAim();
                    standMinTotal += lotData_inner.GetStandMin());
                    if (lotData_inner != lotData)
                        lotDataRemovalList.Add(lotData_inner);
                }

                //Remove all duplicates
                foreach (SPCLotData lotDataToRemove in lotDataRemovalList)
                {
                    sPCLotDataList.Remove(lotDataToRemove);
                }
                lotDataRemovalList.Clear();

                //Set the corresponding standdatas to average
                lotData.SetStandData((standMaxTotal / duplicateLotCount),
                                     (standAimTotal / duplicateLotCount),
                                     (standMinTotal / duplicateLotCount);
                standMaxTotal = 0.0;
                standAimTotal = 0.0;
                standMinTotal = 0.0;
            }
        }

既然我已经确保我的代码对每个人都零意义(当然,也不起作用,因为我正在修改 foreach 循环内的容器),让我解释一下我正在尝试做什么。

所以我有一个这样的数据结构:

identifyString standMax standAim standMin
-----------------------------------------
     AA          3         4         5
     AA          1         2         3
     AA          1         2         4
     AB          0         5         7
     AC          3         4         5

我试图得到的最终结果是:

identifyString standMax standAim standMin
-----------------------------------------
     AA          2.5      2.667      4
     AB          0         5         7
     AC          3         4         5

请注意重复行(具有相同的 identifyString)是如何被删除的,并且唯一剩余的行的值(standMax,aim,min)被更新为它们的平均值。

实现这一目标的最优雅方式是什么?

4

3 回答 3

4

您可以使用 LINQ Enumerable.ToLookup 和 Enumerable.Average 扩展方法

这是我的意思:

 var perIdentStrLookup = sPCMeasureDataList.ToLookup(k => k.GetIdentifyString());
 foreach(var lk in perIdentStrLookup)
 {
       Console.WriteLine("identifyString={0}; standMax={1}; standAim={2}; standMin={1}",
                           lk.Key,//identifyString
                           lk.Average(l=>GetStandMax()),
                           lk.Average(l=>GetStandAim()),
                           lk.Average(l=>GetStandMin()),

) }

或者如果你想要唯一的列表

  var uniqueList = sPCMeasureDataList
            .ToLookup(k => k.GetIdentifyString())
            .Select(lk => new SPCLotData 
            {
                   IdentifyString = lk.Key,
                   StandMax =  lk.Average(l=>GetStandMax()),
                   StandAim = lk.Average(l=>GetStandAim()),
                   StandMin = lk.Average(l=>GetStandMin())
            })
            .ToList()
于 2013-06-04T05:09:46.843 回答
3

您可以使用 LINQ GroupBy

var result = sPCLotDataList.GroupBy(x => x.identifyString)
                .Select(g => new SPCLotData(){
                        identifyString = g.Key,
                        standMax = g.Average(x => x.standMax),
                        standAim  = g.Average(x => x.standAim),
                        standMin = g.Average(x => x.standMin)
                    });
于 2013-06-04T04:54:02.400 回答
0

我假设 sPCLotDataList 是您获取数据的地方?

在这种情况下,您可以:

var result = from x in sPCLotDataList
             group x by x.identifyString into grp
             select new { identifyString = grp.key
                          standMax = grp.Average(c => c.standMax)
                          standAim = grp.Average(c => c.standAim)
                          standMin= grp.Average(c => c.standMin)
                        }
于 2013-06-04T04:59:24.370 回答