C# 如何从迭代法到递归法
我有一个迭代的C#循环,它填充了最多5列的棋盘模式 值是成对的,它总是一个标题,每个列有多个值,并且它将这些值组合成一个非重复的组合 从我能想象的最简单的解决方案开始,在看了它之后,我认为一定有更好的方法来解决这个问题,通过递归的方式 下面是我迄今为止尝试的一个例子:C# 如何从迭代法到递归法,c#,recursion,combinatorics,iteration,C#,Recursion,Combinatorics,Iteration,我有一个迭代的C#循环,它填充了最多5列的棋盘模式 值是成对的,它总是一个标题,每个列有多个值,并且它将这些值组合成一个非重复的组合 从我能想象的最简单的解决方案开始,在看了它之后,我认为一定有更好的方法来解决这个问题,通过递归的方式 下面是我迄今为止尝试的一个例子: List<EtOfferVariant> variants = new List<EtOfferVariant>(); _containers[0].Variant.ForEach(first =&g
List<EtOfferVariant> variants = new List<EtOfferVariant>();
_containers[0].Variant.ForEach(first =>
{
if (_containers.Count > 1)
{
_containers[1].Variant.ForEach(second =>
{
if (_containers.Count > 2)
{
_containers[2].Variant.ForEach(third =>
{
EtOfferVariant va = new EtOfferVariant();
va.OfferVariant1Type = _containers[0].VariantKey;
va.OfferVariant1 = first;
va.OfferVariant2Type = _containers[1].VariantKey;
va.OfferVariant2 = second;
va.OfferVariant3Type = third;
va.OfferVariant3 = _containers[3].VariantKey;
variants.Add(va);
});
}
else
{
EtOfferVariant va = new EtOfferVariant();
va.OfferVariant1Type = _containers[0].VariantKey;
va.OfferVariant1 = first;
va.OfferVariant2Type = second;
va.OfferVariant2 = _containers[1].VariantKey;
variants.Add(va);
}
});
}
else
{
EtOfferVariant va = new EtOfferVariant();
va.OfferVariant1Type = _containers[0].VariantKey;
va.OfferVariant1 = first;
variants.Add(va);
}
});
EtOfferVariant是一个包含这些列的ORM Poco我想您只是想减少重复代码。在这种情况下,只需添加您所知道的数据,并在构建后在末尾添加变量。唯一的问题是,您需要一个复制构造函数来复制以前运行的值
List<EtOfferVariant> variants = new List<EtOfferVariant>();
_containers[0].Variant.ForEach(first =>
{
EtOfferVariant va = new EtOfferVariant();
va.OfferVariant1Type = _containers[0].VariantKey;
va.OfferVariant1 = first;
if (_containers.Count > 1)
{
_containers[1].Variant.ForEach(second =>
{
va = new EtOfferVariant(va);
va.OfferVariant2Type = _containers[1].VariantKey;
va.OfferVariant2 = second;
if (_containers.Count > 2)
{
_containers[2].Variant.ForEach(third =>
{
va = new EtOfferVariant(va);
va.OfferVariant3Type = third;
va.OfferVariant3 = _containers[3].VariantKey;
variants.Add(va);
});
} else
variants.Add(va);
});
} else
variants.Add(va);
});
谢谢你的回复, 马丁·利弗塞奇有点引导我, 这不是一个纯粹的笛卡尔积,因为事实是分组后被展平 电影的方法给了我正确方向的最后一点,我现在用下面的方法解决了这个问题 在第一步中,我为第一个变量生成初始行
List<EtOfferVariant> row = new List<EtOfferVariant>();
_containers.First().Variant.ForEach(o =>
{
row.Add(new EtOfferVariant() { OfferVariant1 = o, OfferVariant1Type = _containers.First().VariantKey });
});
return BuildVariants(row);
我还将列拆分为一个自己的方法,但它所做的只是获取索引并将值映射到对象,没有什么特别之处
再次感谢大家,这真的放松了代码如果您首先转换容器中的字典,似乎您可以通过笛卡尔积得到想要的结果
var containers = new List<Dictionary<string, IEnumerable<string>>>
{
new Dictionary<string, IEnumerable<string>>() {{"Pie", new [] {"Raspberry", "Strawbery"}}},
new Dictionary<string, IEnumerable<string>>() {{"Drink", new [] {"Cola", "Coffee"}}},
new Dictionary<string, IEnumerable<string>>() {{"Bread", new [] {"Bagel", "Pretzel", "Scone"}}},
};
var flatten = containers.Select(dict => dict.SelectMany(c => c.Value.Select(v => new {type = c.Key, name = v})));
foreach (var combo in CartesianProduct(flatten))
{
Console.WriteLine(string.Join(", ", combo.Select(c => c.type + ": " + c.name)));
}
从您的示例来看,您似乎正在尝试创建笛卡尔积。在这种情况下,您可以编写一个通用算法,其中产品中的集合数不必固定:。不过,这并不涉及递归。谢谢你,我以前尝试过这种方法,但我很难通过这种方式将聚合值放入正确的列中,我编辑了这个问题,因为我的输出似乎不清楚
List<EtOfferVariant> row = new List<EtOfferVariant>();
_containers.First().Variant.ForEach(o =>
{
row.Add(new EtOfferVariant() { OfferVariant1 = o, OfferVariant1Type = _containers.First().VariantKey });
});
return BuildVariants(row);
private List<EtOfferVariant> BuildVariants(List<EtOfferVariant> row, int containerIndex = 1)
{
List<EtOfferVariant> final = new List<EtOfferVariant>();
row.ForEach(y =>
{
for (int i = 0; i < _containers[containerIndex].Variant.Count; i++)
{
var ret = MultiplyFromPrevious(y);
FillByIndex(ret, _containers[containerIndex].Index, _containers[containerIndex].VariantKey, _containers[containerIndex].Variant[i]);
final.Add(ret);
}
});
containerIndex++;
if (containerIndex < _containers.Count)
return BuildVariants(final, containerIndex);
return final;
}
private EtOfferVariant MultiplyFromPrevious(EtOfferVariant variant)
{
EtOfferVariant ret = new EtOfferVariant();
ret.OfferVariant1 = variant.OfferVariant1;
ret.OfferVariant2 = variant.OfferVariant2;
ret.OfferVariant3 = variant.OfferVariant3;
ret.OfferVariant4 = variant.OfferVariant4;
ret.OfferVariant5 = variant.OfferVariant5;
ret.OfferVariant1Type = variant.OfferVariant1Type;
ret.OfferVariant2Type = variant.OfferVariant2Type;
ret.OfferVariant3Type = variant.OfferVariant3Type;
ret.OfferVariant4Type = variant.OfferVariant4Type;
ret.OfferVariant5Type = variant.OfferVariant5Type;
return ret;
}
var containers = new List<Dictionary<string, IEnumerable<string>>>
{
new Dictionary<string, IEnumerable<string>>() {{"Pie", new [] {"Raspberry", "Strawbery"}}},
new Dictionary<string, IEnumerable<string>>() {{"Drink", new [] {"Cola", "Coffee"}}},
new Dictionary<string, IEnumerable<string>>() {{"Bread", new [] {"Bagel", "Pretzel", "Scone"}}},
};
var flatten = containers.Select(dict => dict.SelectMany(c => c.Value.Select(v => new {type = c.Key, name = v})));
foreach (var combo in CartesianProduct(flatten))
{
Console.WriteLine(string.Join(", ", combo.Select(c => c.type + ": " + c.name)));
}
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] {item})
);
}
Pie: Raspberry, Drink: Cola, Bread: Bagel
Pie: Raspberry, Drink: Cola, Bread: Pretzel
Pie: Raspberry, Drink: Cola, Bread: Scone
Pie: Raspberry, Drink: Coffee, Bread: Bagel
Pie: Raspberry, Drink: Coffee, Bread: Pretzel
Pie: Raspberry, Drink: Coffee, Bread: Scone
Pie: Strawbery, Drink: Cola, Bread: Bagel
Pie: Strawbery, Drink: Cola, Bread: Pretzel
Pie: Strawbery, Drink: Cola, Bread: Scone
Pie: Strawbery, Drink: Coffee, Bread: Bagel
Pie: Strawbery, Drink: Coffee, Bread: Pretzel
Pie: Strawbery, Drink: Coffee, Bread: Scone