2016-12-16 26 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成功吗? –