嵌套分组策略/算法c#
不确定我是否必须纠正此类问题的标签,但是您对以下问题的通用解决方案有什么想法吗?
给定发票集合:
var invoices = new List<Invoice>()
{
new Invoice() { Id = 1, Customer = "a", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 2, Customer = "a", Date = DateTime.Parse("1/2/2009") },
new Invoice() { Id = 3, Customer = "a", Date = DateTime.Parse("1/2/2009") },
new Invoice() { Id = 4, Customer = "b", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 5, Customer = "b", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 6, Customer = "b", Date = DateTime.Parse("1/2/2009") }
}
我可以使用什么技术来指定类似以下内容:
var tree = invoices.ToHeirarchy(t => {
t.GroupBy(x => x.Date);
t.GroupBy(x => x.Customer);
})
结果如图所示:
Date "1/1/2009"
Customer a
Invoice 1
Customer b
Invoice 4
Invoice 5
Date "1/2/2009"
Customer a
Invoice 2
Invoice 3
Customer b
Invoice 6
并且还允许通过以下内容(允许对任何级别的发票进行计算)?
Assert.AreEqual(3, tree.Node[0].Items.Count)
Assert.AreEqual(DateTime.Parse("1/1/2009"), tree.Node[0].Key)
Assert.AreEqual(3, tree.Node[1].Items.Count)
Assert.AreEqual(DateTime.Parse("1/2/2009"), tree.Node[1].Key)
Assert.AreEqual("a", tree.Node[0].Node[0].Key)
Assert.AreEqual(1, tree.Node[0].Node[0].Items.Count)
Assert.AreEqual("b", tree.Node[0].Node[1].Key)
Assert.AreEqual(2, tree.Node[0].Node[1].Items.Count)
Not sure if I have to correct label for this type of problem, but do you have any thoughts on a generic solution for the following?
Given a collection of Invoices:
var invoices = new List<Invoice>()
{
new Invoice() { Id = 1, Customer = "a", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 2, Customer = "a", Date = DateTime.Parse("1/2/2009") },
new Invoice() { Id = 3, Customer = "a", Date = DateTime.Parse("1/2/2009") },
new Invoice() { Id = 4, Customer = "b", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 5, Customer = "b", Date = DateTime.Parse("1/1/2009") },
new Invoice() { Id = 6, Customer = "b", Date = DateTime.Parse("1/2/2009") }
}
What technique can I use where specifying something like:
var tree = invoices.ToHeirarchy(t => {
t.GroupBy(x => x.Date);
t.GroupBy(x => x.Customer);
})
Results in a graph like:
Date "1/1/2009"
Customer a
Invoice 1
Customer b
Invoice 4
Invoice 5
Date "1/2/2009"
Customer a
Invoice 2
Invoice 3
Customer b
Invoice 6
And also allows the following to pass (allowing for calculations on the invoices from any level)?
Assert.AreEqual(3, tree.Node[0].Items.Count)
Assert.AreEqual(DateTime.Parse("1/1/2009"), tree.Node[0].Key)
Assert.AreEqual(3, tree.Node[1].Items.Count)
Assert.AreEqual(DateTime.Parse("1/2/2009"), tree.Node[1].Key)
Assert.AreEqual("a", tree.Node[0].Node[0].Key)
Assert.AreEqual(1, tree.Node[0].Node[0].Items.Count)
Assert.AreEqual("b", tree.Node[0].Node[1].Key)
Assert.AreEqual(2, tree.Node[0].Node[1].Items.Count)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您正在寻找的术语是“嵌套 groupby”。
http://msdn.microsoft.com/en-us/vcsharp/ aa336754.aspx#nested
The term you're looking for is a "nested groupby".
http://msdn.microsoft.com/en-us/vcsharp/aa336754.aspx#nested
远非可重用,但这应该可以做到:
Far from being reusable but this should do it:
您需要一种能够表示树结构的类型。 框架中有一些类型可以使用 - 例如
KeyValuePair
、树视图节点TreeNode
、XML 元素XmlElement
> 和XElement
,可能还有更多。 以下示例包含两个使用XElement
表示树的解决方案。 一种使用 lambda 来访问成员,另一种使用字符串,两者都有优点和缺点。 我认为可以从具有更复杂代码的解决方案中获得最佳效果。第一个解决方案的输出如下。
第二种解决方案产生以下结果。
该解决方案远非完美,但可能会提供一些起点,并且它们提供了 LINQ to XML 查询树的全部功能。 如果您要大量使用此树,我建议为该树构建一个更适合需求的自定义节点类型。 但设计这个可能会非常困难 - 特别是如果你想要强类型。
最后我想提一下,我无法真正看到这样的结构的用途 - 使用 LINQ to object 直接从列表中获取结果不是更容易吗?
You need a type that is capable of representing the tree structure. There are some types in the framework that could be used - for example
KeyValuePair<TKey, TValue>
, the tree view nodeTreeNode
, XML elementsXmlElement
andXElement
, and probably some more. The following example contains two solutions usingXElement
to represent the tree. One uses lambdas to access the members, the other uses strings and both have pros and cons. I assume it is possible to get the best from solutions with complexer code.The ouput for the first solution is the following.
The second solution yields the following.
This solutions are far from perfect but might offer something to start with and they give the full power of LINQ to XML for querying the tree. If you are going to use this trees heavily, I suggest to build a custome node type for the tree that better fits the needs. But it will probably be quite hard to design this - esspecially if you want strong typing.
Finally I want to mention that I can not really see the use of such an structure - wouldn't it be much easyer to use LINQ to object to obtain the results directly from the list?
您可以按日期和日期对结果进行排序,而不是按树排序。 然后由客户。
Instead of a tree, you could sort the results by Date & then by Customer.
我还没有测试过,但我认为 eulerfx 提出的答案是正确的方向。 下面我用 LINQ 理解语法为此类事情编写了自己的解决方案。
ToList() 调用实际上是可选的,具体取决于您试图在投影中实现的目标。
最近我问了一个类似的问题,看来我可能会自己回答。 如果您认为它可能有助于理解有关使用 linq 分组以创建层次结构的其他选项,请查看它。
I haven't tested it but I think eulerfx's proposed answer is in the right direction. Below I've written my own solution for this type of thing in LINQ comprehension syntax.
The ToList() calls are really optional depending on what your trying to achieve in your projection.
Recently I've asked a similar question and it appears that I may be answering it myself. Please take it look if you think it may help understand other options with regard to grouping with linq to create hierarchies.