使用半复杂的结构,我试图使用Linq Aggregate
方法将几个对象“组合”成一个(尽管如果有更好的方法,我愿意接受这些想法)。
这是我的基本课程设计。
class Aspect {
string Name { get; set; }
}
class Arrangement {
Aspect Aspect { get; set; }
IList<Aperture> Apertures { get; set; }
IList<Step> Steps { get; set; }
}
class Step {
int Rank { get; set; }
int Required { get; set; }
}
class Aperture {
string Name { get; set; }
int Size { get; set; }
}
基本上,我正在尝试聚合IEnumerable<Arrangement>
的整个层次结构并将所有内容保留在基础级别,但是在可以适当覆盖的地方,我想覆盖它们。
我想让所有
Arrangements
共享相同的Aspect.Name
,并获得Steps
的完整列表,覆盖较低级别的排名,其中较高级别的排列具有相同的排名而不同所需的价值。
举个例子......
var list = new List<Arrangement>{
new Arrangement{
Aspect = Aspects.Named("One"),
Steps = new List<Step>{
new Step {
Rank = 1,
Required = 2
},
new Step {
Rank = 2,
Required = 4
}
}
},
new Arrangement{
Aspect = Aspects.Named("One"),
Steps = new List<Step>{
new Step {
Rank = 1,
Required = 3
}
}
}
}
如果正确汇总,它应该看起来像......
Arrangement
- Aspect
- Name : One
- Steps
- Rank : 1
- Required : 3
- Rank : 2
- Required : 4
我试图使用Distinct
和Aggregate
,但这并没有让我到任何地方。我最终没有得到一个列表或另一个列表。任何人都可以帮忙吗?
以下是我当前聚合的一个示例。
public static Layouts.Template Aggregate(this IList<Layouts.Template> source) {
return source.Aggregate(
source.First(),
(current, next) => new Layouts.Template {
Apertures = (current.Apertures.Concat(next.Apertures).Distinct().ToList()),
Arrangements = (current.Arrangements.Concat(next.Arrangements).Distinct().ToList()),
Pages = (current.Pages.Concat(next.Pages).Distinct().ToList())
});
}
我的问题是,我在如何完成这项任务时遇到了很多麻烦,更不用说在一个表达式中。我不是不愿意使用多种方法,但如果我可以将它全部封装起来,那将非常有用。我对LINQ很着迷,我真的很想了解这一点。
另一个集合Apertures
将以类似的方式工作,但它与Steps
无关。只需要两个不同的阵列,我必须做同样的事情,但它们之间没有任何共同之处。学习如何用一个人来做这件事会让我知道如何与另一个人一起做。
答案 0 :(得分:2)
如果步骤和光圈之间没有关联,你可以这样做:
var result = new Arrangement{
Steps = list.SelectMany(arrangement => arrangment.Steps)
.GroupBy(step => step.Rank)
.Select(l => l.Last())
.OrderBy(step => step.Rank)
.ToList()),
}
如果有你需要以某种方式将两者结合起来。如果步骤索引到光圈,那么你可以使用类似的东西。
答案 1 :(得分:1)
更新后:
var query = arrangements
.GroupBy(a => a.Aspect.Name)
.Select(g =>
new Arrangement
{
Steps = ga.SelectMany(a => a.Steps)
.GroupBy(s => s.Rank)
.Select(gs => gs.Last()),
Aspect = ga.First().Aspect
});
这将在您的示例中创建输出。
现在,如何将其与您当前的聚合方法合并?至于我的不足之处,你想从所有当前的布局内容(包括安排,页面等)创建一个大的布局?
您根本不需要聚合,只需将其拆分为3个LINQ查询:
// get all arrangements object from all layouts [flattening with SelectMany]
var arrangements = source.SelectMany(s => s.Arrangements);
// and filter them
var filteredArrangements = // enter larger query from above here
// repeat the same for Apertures and Pages
...
// and return single object
return new Layouts.Template
{
Apertures = filteredApertures,
Arrangements = filteredArrangements,
Pages = filteredPages
};
答案 2 :(得分:1)
我认为不是您想要的完整解决方案:
private static Arrangement Accumulate(IEnumerable<Arrangement> arrangements)
{
var stepsByRank = new Dictionary<int, Step>();
foreach (var arrn in arrangements)
foreach (var step in arrn.Steps)
stepsByRank[step.Rank] = step;
return new Arrangement { Steps = stepsByRank.Values.ToArray() };
}
这有什么缺失?你还想怎样“聚合”这些安排和步骤? (编辑:阅读你的评论后,也许这实际上就是你想要的。)