我有两个总是大小相等的数组,我想找到这两个数组的所有可能的组合集。
例如:
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" },
...
}
答案 0 :(得分:1)
正如许多人在评论中提到的那样,你可以在两个列表之间应用笛卡尔积,然后执行此操作。
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
答案 1 :(得分:1)
在Console项目中,将Program类设为static以启用扩展方法。 要在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你确实需要排列而不是组合