同时使用GroupBy和SelectMany

时间:2012-03-30 02:12:13

标签: c# linq

我已经在这个问题上挣扎了好几个小时了,我开始认为我离兔子洞太远了。在我完全放弃之前,我希望有人能够为我揭开这一点......

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数组。我正在尝试获取一组对象。我正在尝试做什么?

4 个答案:

答案 0 :(得分:1)

这个怎么样:

objects.GroupBy(obj => obj.Properties.First().Value);

objects.GroupBy(obj => obj.Properties.First(p => p.Name == "Level").Value);

答案 1 :(得分:1)

鉴于我现在对您的用例的理解,我建议您使用Dictionary来存储您的属性集,而不是自定义类的列表。这很自然,因为您只需要名称:值对,并且每个名称只需要一个值。

假设你选择var Properties = new Dictionary<string, dynamic>(),这应该为你做分组(给定一个属性名称):

var groupBy = objects.GroupBy(obj => obj.Properties['Level']);

这假设objects中的每个对象在其属性中都有'Level'的值。

答案 2 :(得分:0)

您可以定义一个查询,该查询为您提供每个对象与其可枚举的属性的组合。这样可以轻松浏览并执行您的分组。

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);

答案 3 :(得分:0)

如果你想展示你想要达到的目标会更好吗? 例如

    `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)