同时使用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数组。我正在尝试获取一个对象数组。我想做的事情可能吗?

同时使用GroupBy和SelectMany

这个怎么样:

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)