2016-12-16 25 views
1

請注意:我的問題包含僞代碼!集團項目由它持有

在我的軍隊中,我有腳兵。 每個士兵都是獨一無二的:名字,實力等...

所有的士兵都有庫存。它可以是空的。庫存可以包含:武器,盾牌,其他物品。

我想通過他們的確切庫存來組合我的footsoldiers。

很簡單的例子:

我的集合:

  • 武器:{ 「AK-47」, 「手榴彈」, 「刀」}
  • 盾:{」宙斯盾 「}
  • OtherItems:{」 KevlarVest「} footsoldiers的

收藏。 (計數= 6)

  • 「喬」:{ 「AK-47」, 「凱夫拉爾背心」}
  • 「佛瑞德」:{ 「AK-47」}
  • 「約翰」:{」 AK-47" , 「手榴彈」}
  • 「第一滴血」:{ 「刀」}
  • 「富」:{ 「AK-47」}
  • 「酒吧」:{ 「KevlarVest」}

這些是結果組(count = 5):(已經在特定爲了現在)

  • { 「AK-47」}
  • { 「AK-47」, 「手榴彈」}
  • { 「AK-47」, 「凱夫拉爾背心」}
  • {」刀「}
  • {」 KevlarVest「}

我想通過向組進行排序:武器,然後用盾牌,然後通過特定順序的其他項目中,他們是他們的收藏中聲明。

當我打開庫存組{「Knife」}時,我會找到一個名爲「Rambo」的收集1英尺衛士。

請注意:我已經制作了這個簡化版本,以避免分散您手頭數據的複雜性。在我的商業案例中,我正在使用ConditionalActionFlags,它可能包含某種類型的條件。

因此我提供的TestMethod現在仍然失敗。 您可以重寫GetSoldierGroupings方法,以便TestSoldierGroupings方法成功嗎?

public class FootSoldier 
{ 
    public string Name { get; set; } 
    public string[] Inventory { get; set; } 
} 

public class ArrayComparer<T> : IEqualityComparer<T[]> 
{ 
    public bool Equals(T[] x, T[] y) 
    { 
     return x.SequenceEqual(y); 
    } 

    public int GetHashCode(T[] obj) 
    { 
     return obj.Aggregate(string.Empty, (s, i) => s + i.GetHashCode(), s => s.GetHashCode()); 
    } 
} 

[TestMethod] 
public void TestSoldierGroupings() 
{ 
    //Arrange 
    var weapons = new[] { "AK-47", "Grenade", "Knife" }; 
    var shields = new[] { "Aegis" }; 
    var otherItems = new[] { "KevlarVest" }; 

    var footSoldiers = new FootSoldier[] 
    { 
     new FootSoldier() { Name="Joe" , Inventory= new string[]{ "AK-47", "Kevlar Vest" } }, 
     new FootSoldier() { Name="Fred" , Inventory= new string[]{ "AK-47" } }, 
     new FootSoldier() { Name="John" , Inventory= new string[]{ "AK-47", "Grenade" } }, 
     new FootSoldier() { Name="Rambo" , Inventory= new string[]{ "Knife" } }, 
     new FootSoldier() { Name="Foo" , Inventory= new string[]{ "AK-47" } }, 
     new FootSoldier() { Name="Bar" , Inventory= new string[]{ "Kevlar Vest" } } 
    }; 

    //Act 
    var result = GetSoldierGroupings(footSoldiers, weapons, shields, otherItems); 
    //Assert 
    Assert.AreEqual(result.Count, 5); 
    Assert.AreEqual(result.First().Key, new[] { "AK-47" }); 
    Assert.AreEqual(result.First().Value.Count(), 2); 
    Assert.AreEqual(result.Last().Key, new[] { "Kevlar Vest" }); 
    Assert.AreEqual(result[new[] { "Knife" }].First().Name, "Rambo"); 
} 

public Dictionary<string[], FootSoldier[]> GetSoldierGroupings(FootSoldier[] footSoldiers, 
    string[] weapons, 
    string[] shields, 
    string[] otherItems) 
{ 
    //var result = new Dictionary<string[], FootSoldier[]>(); 
    var result = footSoldiers 
     .GroupBy(fs => fs.Inventory, new ArrayComparer<string>()) 
     .ToDictionary(x => x.Key, x => x.ToArray()); 

    //TODO: the actual sorting. 

    return result; 
} 
+0

哦,如果一個footsoldier在庫存中沒有物品,那就是它自己的一組物品,在排序之上:-) –

+0

您可以列舉庫存物品的可能組合,並將該enum作爲士兵的屬性 – ldgorman

+0

聽起來像標準的LINQ'GroupBy'和最終的自定義比較器。你嘗試過什麼嗎?有什麼問題? –

回答

1

你需要通過組合項目的鑰匙來組合你的士兵。它可以使用自定義比較器來完成。
至於我,我會更簡單通過使用String.Join與分離不能在任何武器得到滿足,屏蔽等

假設一個士兵有一個屬性Items這是一個字符串數組(如["AK-47", "Kevlar Vest"])你可以做這樣的事情:

var groups = soldiers 
    .GroupBy(s => String.Join("~~~", s.Items)) 
    .ToDictionary(g => g.First().Items, g => g.ToArray()); 

這將導致到字典,其中關鍵是唯一的項目設置,和價值是具有這樣集中的所有士兵的數組。

您可以更改此代碼,使其返回IGrouping,這是類\ structs,Dictionary的數組,其他任何方便您都方便。
我會去Dictionary或一些像SoldiersItemGroup[]東西的物品和士兵的屬性。
確保更改此類連接分隔符,以使武器無法在理論上包含它。

+0

謝謝,我會評估... –

+0

我已經使用了ToDictionary()方法。但我不得不補充:'public class ArrayComparer :IEqualityComparer '。你能幫我整理一下,以便TestMethod成功嗎? –