同时使用GroupBy和SelectMany
本文关键字:SelectMany GroupBy | 更新日期: 2023-09-27 18:29:39
我已经解决这个问题几个小时了,我开始觉得我太落后了。在我完全放弃之前,我希望有人能为我阐明这一点…
public class Object
{
public Object()
{
Properties = new List<Property>();
}
public int Id { get; set; }
public IList<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public dynamic Value { get; set; }
}
[Test]
public void ShouldBeAbleToGroupAnArrayOfObjectsByASpecificProperty()
{
// Arrange
var objects = new List<Object>();
var doorObject = new Object() {
Properties = new List<Property>() {new Property() {Name = "Level", Value = "Level 1"}}
};
var wallobject = new Object() {
Properties = new List<Property>() { new Property() { Name = "Level", Value = "Level 2" } }
};
var chairObject = new Object() {
Properties = new List<Property>() { new Property() { Name = "Level", Value = "Level 2" } }
};
objects.Add(doorObject);
objects.Add(wallobject);
objects.Add(chairObject);
// Act
var groupBy = objects.SelectMany(obj => obj.Properties).GroupBy(props => props.Value);
// Assert
Assert.That(groupBy.Count(), Is.EqualTo(2));
}
这个测试通过了,但问题是我返回了一个Properties数组。我正在尝试获取一个对象数组。我想做的事情可能吗?
这个怎么样:
objects.GroupBy(obj => obj.Properties.First().Value);
或
objects.GroupBy(obj => obj.Properties.First(p => p.Name == "Level").Value);
鉴于我现在对您的用例的了解,我建议只使用Dictionary
来存储您的属性集,而不是使用自定义类的列表。这是自然的匹配,因为您只需要名称:值对,并且每个名称只需要一个值。
假设您使用var Properties = new Dictionary<string, dynamic>()
,这将为您进行分组(给定属性名称):
var groupBy = objects.GroupBy(obj => obj.Properties['Level']);
不过,这假设objects
中的每个对象在其属性中都有一个'Level'
的值。
您可以定义一个查询,该查询将每个对象及其属性组合在一个可枚举的网络中。这使得导航和执行您的小组很容易。
var stretched = objects.SelectMany(x => x.Properties, (x, property) => new
{
Object = x,
Property = property
});
var q = stretched.GroupBy(x => x.Property.Value, x => x.Object);
如果你想展示你想要实现的目标,那会更好吗?例如
`Object A - property 1 {Name = "a"}, 2 {Name = "b"}, 3 {Name = "a"}`
`Object B - property 1 {Name = "a"}, 2 {Name = "b"}, 3 {Name = "a"}`
How do you want to group
object A - property.Name = "a", values - 1, 3
property.Name = "b", values - 2
object B - property.Name = "a", values - 1, 3
property.Name = "b", values - 2
或
property.Name = "a", values - 1, 3 (objectA), 1, 3 (object B)
property.Name = "b", values - 2 (objectA), 2 (object B)
或
property.Name = "a", a dictionary A (key - object A, values - 1, 3), a dictionary B (key - object B, values - 1, 3)
property.Name = "b", a dictionary A (key - object A, values - 2), a dictionary B (key - object B, values - 2)