请允许我先向您提出我残暴的逻辑:
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)将更新为其平均值。
实现这一目标最优雅的方式是什么?
答案 0 :(得分: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()
答案 1 :(得分: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)
});
答案 2 :(得分: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)
}