我有一个与组合相关的问题。
我实际上正在开发一个电子商务网站,并且我有一个允许客户创建产品变体的功能。
例如:黑色裤子 34W 30L、黑色裤子 38W 32L、白色裤子 34W 30l。这些被定义为产品变体。
假设我的裤子有 3 个选项,分别是颜色、腰围和长度。
我现在有 3 个列表。
ListA = {"black", "white", "red"} //For the color
ListB = {30,32,34,36,38} //For the waist
ListC ={28,30,32,34} //For the length
我的问题是如何列出所有可能的组合?
我想要的结果应该是 {{black,30,28},{black,30,30},{black,30,32},{white,34
,30}
附言棘手的部分是我不知道客户会为该产品分配多少选项。选项的个数可能只有1,这是最简单的;可能超过 3...
问题已解决
因为我们不知道我们会有多少选择。因此,我们不知道要使用多少个 for 循环。换句话说,它变成了一个典型的笛卡尔积。
有关更多信息,您可以从这两个链接中阅读。
http://www.interact-sw.co.uk/iangblog/2010/07/28/linq-cartesian-1
http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx
谢谢大家的帮助!
如评论中所述,Eric Lippert 有一篇名为 Computing a Cartesian Product with LINQ 的博客文章这说明了如何解决您的问题。您需要一种扩展方法来计算笛卡尔积:
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) {
IEnumerable<IEnumerable<T>> result = new [] { Enumerable.Empty<T>() };
foreach (var sequence in sequences) {
var localSequence = sequence;
result = result.SelectMany(
_ => localSequence,
(seq, item) => seq.Concat(new[] { item })
);
}
return result;
}
然后您需要一系列序列来执行产品。在您的情况下,您的序列中同时包含字符串和整数,因此通用基本类型 T
必须是 Object
。
var sequences = new[] {
new Object[] { "black", "white", "red" },
new Object[] { 30, 32, 34, 36, 38 },
new Object[] { 28, 30, 32, 34 }
};
要计算笛卡尔积,您只需调用扩展方法:
var result = sequences.CartesianProduct();
当您枚举结果时,它是动态计算的(惰性的)。如果您更喜欢创建列表列表,您需要在 Concat
之后以及从扩展方法返回 result
之前调用 ToList()
。