2012-03-30 3 views
1

Я уже несколько часов борюсь с этой проблемой, и я начинаю думать, что я слишком далеко от кроличьей дыры. Перед тем, как отказаться полностью, я надеюсь, что кто-то мог бы пролить некоторый свет на это для меня ...Использование GroupBy и SelectMany в унисон

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

Этот тест проходит, но проблема в том, что я возвращаюсь массив свойств. Я пытаюсь получить массив объектов. Это то, что я пытаюсь сделать возможным?

+0

Если я правильно понимаю, вы пытаетесь сгруппировать объекты по свойству «Уровень» - что бы вы хотели, если бы существовал объект с множеством разных значений? – tzaman

+0

@tzaman - Я не совсем уверен, что понял вопрос? Свойства могут иметь разные значения. В приведенном выше примере я хотел бы получить конечный результат: сгруппированный набор объектов, все сгруппированные по значению «Свойство» их коллекции свойств. На данный момент меня действительно не интересует отрицательный тестовый пример. Это помогает? –

+0

Если в этой коллекции есть разные значения, в какую группу должен идти объект? то есть, если fooObject сказал, что оба уровня «Уровень 1» и «Уровень 2» в его наборе свойств должны быть в двух группах? – tzaman

ответ

1

Как об этом:

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

или

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

Андрей, я не могу вас поблагодарить, сэр , Я три дня бил головой о клавиатуру и не мог поверить, что не заметил этого. Так просто. Огромное спасибо. –

+0

Действительно ли это правильное решение? Как я понимаю, вы хотите группировать объекты вместе на основе свойства соответствия. В этом решении вы отвечаете за первое свойство. – Polity

+0

Я пока не даю ему правильного решения, потому что утром я отправлю его на тест.Однако второй вариант ищет первое свойство с именем «Уровень». В конечном счете, именно это я и хочу сгруппировать. –

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

Я, конечно же, дам этот снимок. Спасибо, Полити. –

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

Учитывая то, что теперь я понимаю, что ты прецедент, я хотел бы предложить только с помощью Dictionary для хранения набора свойств, вместо списка пользовательского класса. Это естественная подгонка, так как вам просто нужны пары имя: значение, и вам нужно только одно значение для каждого имени.

Предполагая, что вы идете с var Properties = new Dictionary<string, dynamic>(), это должно сделать свою группировку для вас (дано имя свойства):

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

Это предполагает, что каждый объект в objects имеет значение для 'Level' в его свойствах, хотя.

+0

Если честно, это именно то, что я собираюсь изменить. Я попытаюсь реализовать PropertyCollection, который наследует от KeyedCollection в надежде, что он обеспечивает более простой интерфейс для добавления элементов в словарь. Спасибо, что выпустили мою лампочку. –