如何创建一组新的词典,其中包含列表为值的字典中的所有可能组合

时间:2014-10-31 20:50:12

标签: c# dictionary combinations

我需要将带有字符串键和字符串列表的字典作为值,并找到它可以进行的所有组合。 例如:

var myDictionary = new Dictionary<string, List<string>>
{
    {"X", new List<string> {"x", "y", "z"}},
    {"Y", new List<string> {"x", "y"}},
    {"Z", new List<string> {"a", "b"}}
};

将翻译为:

{X: x, Y: x, Z: a}
{X: x, Y: x, Z: b}
{X: x, Y: y, Z: a}
{X: x, Y: y, Z: b}
{X: y, Y: x, Z: a}
{X: y, Y: x, Z: b}
{X: y, Y: y, Z: a}
{X: y, Y: y, Z: b}
{X: z, Y: x, Z: a}
{X: z, Y: x, Z: b}
{X: z, Y: y, Z: a}
{X: z, Y: y, Z: b}

我怎样才能以最聪明的方式做到这一点?

2 个答案:

答案 0 :(得分:3)

这样做怎么样?

var combinations =
    from x in myDictionary["X"]
    from y in myDictionary["Y"]
    from z in myDictionary["Z"]
    select new Dictionary<string, string>()
    {
        { "X", x },
        { "Y", y },
        { "Z", z },
    };

我得到了这个结果:

combinations


在进一步考虑之后,这里有一种计算字典中任意数量元素的方法(即不只是“X”,“Y”和“Z”。)

Func<
    Dictionary<string, string>,
    Dictionary<string, string>,
    Dictionary<string, string>> merge = (d1, d2) =>
{
    var d = new Dictionary<string, string>(d1);
    foreach (var kv in d2)
    {
        d.Add(kv.Key, kv.Value);
    }
    return d;
};

var combinations =
    myDictionary
        .Select(x =>
            x.Value.Select(v =>
                new Dictionary<string, string>()
                {
                    { x.Key, v }
                }))
        .Aggregate((xs, vs) =>
            from x in xs
            from v in vs
            select merge(x, v));

答案 1 :(得分:1)

这适用于您的具体示例。希望这会给你一个开始,并且它不应该太难以使它适用于更通用的方法:

var dict = new Dictionary<string, List<string>>
{
    {"X", new List<string> {"x", "y", "z"}},
    {"Y", new List<string> {"x", "y"}},
    {"Z", new List<string> {"a", "b"}}
};

var combiDicts = new List<Dictionary<string, string>>();
foreach (var entryXItem in dict["X"])
{
    foreach (var entryYItem in dict["Y"])
    {
        foreach (var entryZItem in dict["Z"])
        {
            combiDicts.Add(new Dictionary<string, string>
            {
                {"X", entryXItem}, {"Y", entryYItem}, {"Z", entryZItem}
            });
        }
    }
}

测试:

foreach (var d in combiDicts)
    Console.WriteLine("{{X: {0}, Y: {1}, Z: {2}}}", d["X"], d["Y"], d["Z"]);

输出:

{X: x, Y: x, Z: a}
{X: x, Y: x, Z: b}
{X: x, Y: y, Z: a}
{X: x, Y: y, Z: b}
{X: y, Y: x, Z: a}
{X: y, Y: x, Z: b}
{X: y, Y: y, Z: a}
{X: y, Y: y, Z: b}
{X: z, Y: x, Z: a}
{X: z, Y: x, Z: b}
{X: z, Y: y, Z: a}
{X: z, Y: y, Z: b}