【问题标题】:Find all combination sets of two equally sized arrays in C#在 C# 中查找两个大小相等的数组的所有组合集
【发布时间】:2016-06-08 18:02:30
【问题描述】:

我有两个大小总是相等的数组,我想找到这两个数组所有可能的组合集。

例如:

var names = new [] { "John", "Alex", "Peter", "Eric" };
var letters = new [] { "A", "B", "C", "D" };

我希望将结果作为字典列表返回:

var combinationSets = new List<Dictionary<string, string>>
        {
            new Dictionary<string, string>
            { {"John", "A"},
            {"Alex", "B"},
            {"Peter", "C"},
            {"Eric", "D"}},
            new Dictionary<string, string>
            { {"John", "B"},
            {"Alex", "C"},
            {"Peter", "D"},
            {"Eric", "A"}},
            ...
        };

编辑:两个数组中的值都不能在字典中重复,例如:

new Dictionary<string, string>
                { {"John", "A"},
                {"Alex", "A"},
                {"Peter", "C"},
                {"Eric", "D"}}

关于如何解决这个问题的任何提示?

编辑: 我不认为可以使用笛卡尔积,因为它会返回

var cartesianProduct= new []
{ 
new []{ "John", "A" }, 
new []{ "Alex", "B" },     
new []{ "Peter", "C" }, 
new []{ "John", "D" }, 
new []{ "John", "B" }, 
new []{ "Alex", "C" },     
new []{ "Peter", "D" }, 
new []{ "John", "A" }, 
... 
}

【问题讨论】:

  • 您尝试过吗?这有家庭作业的味道,不是吗?如果是,您应该阅读guidelines on homework questions,特别是[OP 应该](就是您)真诚地尝试自己先解决问题。您还应该阅读help center
  • 您正在寻找的是笛卡尔积。这里有很多解决方案。
  • 是的,已经尝试过使用笛卡尔积,但正如我所见,我不会得到一组组合,但只有一个包含两个列表组合的列表,例如:var cartesianProduct= new []{ new []{ "John", "A" }, new []{ "Alex", "B" }, ... }

标签: c# asp.net


【解决方案1】:

在控制台项目中,将 Program 类设为静态以启用扩展方法。 要在 asp.net 中使用它,请创建一个 Main 方法并为其他函数创建一个静态帮助器类。

    static void Main(string[] args)
    {
        var names = new[] { "John", "Alex", "Peter", "Eric" };
        var letters = new[] { "A", "B", "C", "D" };

        var combinationSets = new List<Dictionary<string, string>>();
        foreach (var seq in letters.Permutate(4))
        {
            var dic = new Dictionary<string, string>();
            var vals = seq.ToArray();
            for (int i = 0; i < 4; i++)
            {
                dic.Add(names[i], vals[i]);
            }
            combinationSets.Add(dic);
        }

        foreach (var dic in combinationSets)
        {
            foreach (var p in dic)
            {
                Console.WriteLine(p.Key + ": " + p.Value);
            }
            Console.WriteLine();
        }
        Console.ReadLine();
    }

public static IEnumerable<IEnumerable<T>> Permutate<T>(this IEnumerable<T> elements, int places, bool allowRepeats = false)
{
    foreach (var cur in elements)
    {
        if (places == 1) yield return cur.Yield();
        else
        {
            var sub = allowRepeats ? elements : elements.ExceptOne(cur);   
            foreach (var res in sub.Permutate(places - 1, allowRepeats))
            {
                yield return res.Prepend(cur);
            }
        }
    }
}

    public static IEnumerable<T> Yield<T>(this T item)
    {
        yield return item;
    }

    static IEnumerable<T> Prepend<T>(this IEnumerable<T> rest, T first)
    {
        yield return first;
        foreach (var item in rest)
            yield return item;
    }


    public static IEnumerable<T> ExceptOne<T>(this IEnumerable<T> src, T e, int n = 1)
    {
        foreach (var x in src)
            if (!x.Equals(e) || n-- == 0) yield return x;
    }

ps 你确实需要 Permutations 而不是 Combinations

【讨论】:

    【解决方案2】:

    正如许多人在 cmets 中提到的,您可以在两个列表之间应用笛卡尔积并执行此操作。

    Logic 执行笛卡尔积,然后为每个结果提供索引,该索引用于分割和形成每个组(因为您希望每个组都作为字典)。

        var names = new [] { "John", "Alex", "Peter", "Eric" };
        var letters = new [] { "A", "B", "C", "D" };
    
    
        int index =0;   
        var results = letters.SelectMany(x => names, (x, y) => new {x, y, idx = index++})
            .GroupBy(x=>x.idx/names.Length)  // Slice each group
            .Select(x=> x.ToDictionary(s=>s.y, s=> s.x))
            .ToList();
    

    输出

    Dumping object(System.Collections.Generic.Dictionary`2[String,String])
    [
       [John, A]
       ,
       [Alex, A]
       ,
       [Peter, A]
       ,
       [Eric, A]
    ]
    Dumping object(System.Collections.Generic.Dictionary`2[String,String])
    [
       [John, B]
       ,
       [Alex, B]
       ,
       [Peter, B]
       ,
       [Eric, B]
    ]
    Dumping object(System.Collections.Generic.Dictionary`2[String,String])
    [
       [John, C]
       ,
       [Alex, C]
       ,
       [Peter, C]
       ,
       [Eric, C]
    ]
    Dumping object(System.Collections.Generic.Dictionary`2[String,String])
    [
       [John, D]
       ,
       [Alex, D]
       ,
       [Peter, D]
       ,
       [Eric, D]
    ]
    

    查看Demo

    【讨论】:

    • 这并不能解决问题。这里只有4种组合。我们应该得到 24。每个数组中的项都不能在任何字典中重复。
    • 在你提到的问题中你想要这个输出,现在你说这不是想要的解决方案。你能解释更多吗?
    • 我说我想要那个输出,是的,但我也想要所有组合而不重复任何值。
    • 不重复任何值是什么意思?你能举个例子解释一下吗?
    • 我明白了,你的意思。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    相关资源
    最近更新 更多