2012-03-30 47 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

如果我理解正確,您試圖按照其「Level」屬性對對象進行分組 - 如果存在具有多個不同值屬性的對象,您希望發生什麼? – tzaman 2012-03-30 02:19:07

+0

@tzaman - 我不太確定我是否理解這個問題?屬性當然可以有不同的值。在上面的例子中,我希望得到一個最終結果:一組分組的對象,所有對象都按其屬性集合的「值」分組。目前我並不擔心一個負面的測試案例。這有幫助嗎? – 2012-03-30 02:27:17

+0

如果它在該集合中具有不同的值,哪個組是應該進入的對象?即如果fooObject在其屬性集中同時表示「級別1」和「級別2」,是否應該分爲兩組? – tzaman 2012-03-30 02:32:07

回答

1

如何:

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

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

安德魯,我不能夠感謝你,先生。我一直在敲着鍵盤三個小時,不敢相信我沒注意到。很簡單。非常感謝。 – 2012-03-30 02:31:06

+0

這真的是正確的解決方案嗎?據我瞭解,你想根據匹配屬性將對象組合在一起。在這個解決方案中,您可以匹配第一個屬性。 – Polity 2012-03-30 02:38:52

+0

我還沒有給它正確的解決方案,因爲我準備在早上進行測試。但是,第二個選項查找名爲「Level」的第一個屬性。最終,這就是我想要分組的內容。 – 2012-03-30 02:42:37

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

我一定會給這個鏡頭。謝謝你,政體。 – 2012-03-30 02:33:01

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

說實話,這正是我要改變的。我將試圖實現一個繼承自KeyedCollection 的PropertyCollection,希望它提供了一個更簡單的接口來添加項目到Dictionary中。感謝您踢我的燈泡。 – 2012-03-30 14:13:01