我有一个现有的控股列表,我想合并在另一个控股列表。我知道使用foreach & for循环是一种不好的方法,但我想不出使用LINQ来减少这一点的好方法。
private void CombineHoldings(List<Holding> holdingsToAdd, ref List<Holding> existingHoldings)
{
foreach (Holding holdingToAdd in holdingsToAdd)
{
Boolean found = false;
for (int i = 0; i < existingHoldings.Count; i++)
{
if (existingHoldings[i].Sector == holdingToAdd.Sector)
{
found = true;
existingHoldings[i].Percentage += holdingToAdd.Percentage;
}
}
if (!found)
existingHoldings.Add(holdingToAdd);
}
foreach (Holding holding in existingHoldings)
holding.Fund = "Combined Funds";
}发布于 2012-04-28 09:51:59
让函数修改原始列表使得它非常不是Linq,所以这里有一个版本,它将两个列表视为不可变的:
private List<Holding> CombineHoldings(
List<Holding> holdingsToAdd,
List<Holding> existingHoldings)
{
var holdings = existingHoldings.Concat(holdingsToAdd)
.GroupBy(h => h.Sector)
.Select(g =>
{
var result = g.First();
result.Percentage = g.Select(h => h.Percentage).Sum();
return result;
});
return holdings.ToList();
}肯定不会赢得性能竞赛,但我喜欢它的简单性。下面的代码可能会更快,但会更复杂,需要您覆盖控股上的相等以比较扇区或创建一个IEqualityComparer<Holding>
private List<Holding> CombineHoldings(
List<Holding> holdingsToAdd,
List<Holding> existingHoldings)
{
var holdings = existingHoldings.GroupJoin(holdingsToAdd, h => h, h => h,
(h, toAdd) =>
new Holding(
h.Sector,
/*Other parameters to clone*/,
h.Percentage + toAdd.Select(i => i.Percentage).Sum())
).ToList();
holdings.AddRange(holdingsToAdd.Except(holdings));
return holdings;
};发布于 2012-04-28 08:36:48
如果您经常在列表中调用此方法,那么我建议将其放入列表类型的扩展方法中,即
private static void CombineHoldings(this List<Holding> holdingsToAdd, ref List<Holding> existingHoldings)
{
foreach (Holding holdingToAdd in holdingsToAdd)
{
Boolean found = false;
for (int i = 0; i < existingHoldings.Count; i++)
{
if (existingHoldings[i].Sector == holdingToAdd.Sector)
{
found = true;
existingHoldings[i].Percentage += holdingToAdd.Percentage;
}
}
if (!found)
existingHoldings.Add(holdingToAdd);
}
foreach (Holding holding in existingHoldings)
holding.Fund = "Combined Funds";
}这将允许您在创建了列表的任何位置
List<Holding> temp1 = new List<Holding>();
List<Holding> temp2 = new List<Holding>();
//add here to temp1 and temp2
//then...
temp1.CombineHoldings(temp2);将第一个方法设为静态,并在第一个参数前面放一个'this‘关键字,这意味着它将扩展该类型
看一下参数,尽管切换这两个参数可能更有意义,这样它就会添加到调用方法的列表中,如下所示-
private static void CombineHoldings(this List<Holding> existingHoldings, List<Holding> holdingsToAdd)发布于 2012-04-28 09:10:30
我可能会这样说:
private void CombineHoldings(List<Holding> holdingsToAdd, ref List<Holding> existingHoldings)
{
// group the new holdings by sector
var groupedHoldings = holdingsToAdd.GroupBy(h => h.Sector);
// now iterate over the groupings
foreach(var group in groupedHoldings) {
// calculate the sum of the percentages in the group
// we'll need this later
var sum = group.Sum(h => h.Percentage);
// get the index of a matching object in existing holdings
var existingHoldingIndex = existingHoldings.FindIndex(h => h.Sector == group.Key);
// yay! found one. add the sum of the group and our job's done.
if(existingHoldingIndex >= 0) {
existingHoldings[existingHoldingIndex].Percentage += sum;
continue;
}
// didn't find one, so take the first holding in the group, set its percentage to the sum
// and append that to the existing holdings table
var newHolding = group[0];
newHolding.Percentage = sum;
existingHoldings.Add(newHolding);
}
}在性能方面,我不确定这是如何维持的。但它看起来更优雅一些。
https://stackoverflow.com/questions/10359231
复制相似问题