【问题标题】:How can I make a new set of dictionaries containing all the possible combinations from a dictionary with list as value如何制作一组新的字典,其中包含字典中所有可能的组合,列表为值
【发布时间】:2014-10-31 20:50:11
【问题描述】:

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

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}

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

【问题讨论】:

  • 您需要使用字典吗?
  • 你知道排列吗?
  • 在 sql server 中使用交叉连接
  • 您正在寻找的东西称为“笛卡尔积”
  • 这个问题可能会有所帮助:Generating all Possible Combinations

标签: c# dictionary combinations


【解决方案1】:

这样做怎么样?

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 },
    };

我得到这个结果:


经过进一步思考,这里有一种方法可以计算字典中任意数量的元素(即不仅仅是“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));

【讨论】:

    【解决方案2】:

    这将适用于您的具体示例。希望这可以为您提供一个开始,并且让它适用于更通用的方法应该不会太难:

    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}
    

    【讨论】:

    • 我认为输出需要是List&lt;Dictionary&lt;string, string&gt;&gt;(这不难转换成你的答案)
    • 从原始未更新问题中示例的语法看来,他期待字典输入到字典输出。
    • @RufusL:看标题:“我怎样才能制作一套新的字典”。但是,应该很简单,每个字典都包含一个 x-key/value、一个 y-key/value 和一个 z-key/value。
    • 我想我不明白他在寻找什么。在他的输出中,任何行都没有唯一键...您需要组合 x、y 和 z 以获得每行的唯一键。当你拿到那把钥匙时,它的价值是什么?
    • @RufusL:你可以添加这个:combiDicts.Add(new Dictionary&lt;string, string&gt; { {"X", entryXItem}, {"Y", entryYItem}, {"Z", entryZItem} }); +1,即使它可能包含重复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-05
    • 2020-07-16
    • 1970-01-01
    相关资源
    最近更新 更多