请注意:我的问题包含伪代码!
我的军队里有步兵。
每个士兵都是独一无二的:名字,力量等等。
所有士兵都有库存它可以是空的。
库存可以包含:武器,盾牌,其他物品。
我想把我的步兵按精确的库存分类。
非常简单的例子:
我收藏了:
武器:{“AK-47”,“手榴弹”,“刀”}
盾牌:{“宙斯盾”}
其他项目:{“KevlarVest”}
步兵集合。(计数=6)
“乔”:{“AK-47”,“凯夫拉背心”}
“Fred”:{“AK-47”}
“约翰”:{“AK-47”,“手榴弹”}
“兰博”:{“刀”}
“foo”:{“ak-47”}
“bar”:{“kevlarvest”}
这些是生成的组(count=5):(现在已经按特定顺序)
{“AK-47”}
{“ak-47”,“手榴弹”}
{“AK-47”,“芳纶背心”}
{“刀”}
{“kevlarvest”}
我想按以下分类:武器,然后是盾牌,然后是其他物品,按照它们在收藏中的具体申报顺序。
当我打开目录组{“刀”}时,我会发现一个收藏有一个名叫“兰博”的步兵。
请注意:我已经做了这个简化的版本,以不分散你的数据复杂的手头。在我的业务案例中,我使用的是conditionalActionFlags,它可以保存某种类型的条件。
在此,我提供一个现在仍然失败的测试方法。
你能重写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;
}

最佳答案

你需要用一把组合物品的钥匙把你的士兵分组。可以使用自定义比较器完成。
对于我来说,我会通过使用String.Join和任何武器、盾牌等都不会遇到的分隔符来简化它。
假设一个士兵有一个属性Items,它是一个字符串数组(如["AK-47", "Kevlar Vest"]),您可以这样做:

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

它将生成一个字典,其中key是唯一的item set,value是所有拥有该set的士兵的数组。
您可以更改此代码,使其返回IGrouping、类数组\结构,Dictionary,其他任何方便的内容。
我会选择一个Dictionary或者一个类似SoldiersItemGroup[]的数组,把物品和士兵作为属性。
一定要更改这样的连接分隔符,使任何武器理论上都不能包含它。

关于c# - 将项目按其持有的项目分组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41184575/

10-11 03:33