这个问题实际上与 this SO post 相同,只是我正在寻找一个VB.NET (.NET 4) 解决方案。我已经花了很长时间试图想出一个通用的解决方案来解决这个“电源组”问题。
鉴于:
Dim choices As IEnumerable(Of String) = {"Coffee", "Tea", "Milk", "Cookies"}
Dim choiceSets = choices.CombineAll()
我正在寻找 choiceSets
成为 IEnumerable(Of IEnumerable(Of T))
这样我就可以做类似的事情:
For each choiceSet in choiceSets
Console.WriteLine(String.Join(", ", choiceSet))
Next
并得到如下所示的结果
Coffee
Tea
Milk
Cookies
Coffee, Tea
Coffee, Milk
Coffee, Cookies
Tea, Milk
Tea, Cookies
Milk, Cookies
Coffee, Tea, Milk
Coffee, Tea, Cookies
Coffee, Milk, Cookies
Tea, Milk, Cookies
Coffee, Tea, Milk, Cookies
:您可以看到,这是来自源 IEnumerable(Of T)
的每个非重复组合(其中可能有 1 到多个项目 - 本示例只有 4 个) ,它根据源 IEnumerable(Of T)
中项目的顺序进行操作,并且列表中的每个项目 >= 内部 IEnumerable(Of T)
。
无论如何,这不是家庭作业;而是家庭作业。尽管感觉确实如此。
编辑:更新了示例,使其看起来不像结果按字母顺序排序,以强调使用源 IEnumerable(Of T)
的现有顺序,并添加了第四个选择来澄清排序要求每组内。
This question is virtually the same as this SO post, only I'm looking for a VB.NET (.NET 4) solution. I've spun my wheels long enough trying to come up with a generic solution to solving this "power set" problem.
Given:
Dim choices As IEnumerable(Of String) = {"Coffee", "Tea", "Milk", "Cookies"}
Dim choiceSets = choices.CombineAll()
I'm looking for choiceSets
to be an IEnumerable(Of IEnumerable(Of T))
so that I can do something like:
For each choiceSet in choiceSets
Console.WriteLine(String.Join(", ", choiceSet))
Next
And get results that look like:
Coffee
Tea
Milk
Cookies
Coffee, Tea
Coffee, Milk
Coffee, Cookies
Tea, Milk
Tea, Cookies
Milk, Cookies
Coffee, Tea, Milk
Coffee, Tea, Cookies
Coffee, Milk, Cookies
Tea, Milk, Cookies
Coffee, Tea, Milk, Cookies
As you can see, this is every non-repeating combination from the source IEnumerable(Of T)
(which could have 1 to many items in it - this example only had 4), it operates based on the order of the items in the source IEnumerable(Of T)
, and each item in the list is >= the previous item in terms of number of items in the inner IEnumerable(Of T)
.
For what it's worth, this is not homework; though it sure does feel like it.
EDIT: Updated the example so it does not look like the result is alphabetically sorted, to stress that the source IEnumerable(Of T)
's existing order is used and added a 4th choice to clarify the sorting requirement within each set.
发布评论
评论(6)
这是一个纯粹的 Linq 解决方案,灵感来自 Eric Lippert 的 关于计算笛卡尔积的博客文章。我稍微修改了
CartesianProduct
方法,使其返回组合:基于此扩展方法,您可以生成所需的结果,如下所示:(
连接 1, 2... N 项的所有组合)
它 这可能不是一个非常有效的解决方案,但我认为这是 Linq 的一个有趣的使用...
编辑:这是一个新版本的
Combinations
方法,它保持原始顺序:可能比以前的版本,但它完成了工作......
Here's a pure Linq solution, inspired by Eric Lippert's blog post about computing a cartesian product. I modified the
CartesianProduct
method slightly so that it returns combinations:Based on this extension method, you can produce the desired result as follows:
(it concatenates all combinations of 1, 2... N items)
Note that it's probably not a very efficient solution, but I think it's an interesting use of Linq...
EDIT: here's a new version of the
Combinations
method that maintains the original order:Probably even more inefficient than the previous version, but it gets the job done...
如果它对其他人有用,我已经转换了 Thomas Levesque 发布到 VB.NET 的原始 C# 扩展:
必须调用 Repeat n 次才能生成包含所有可能值 n 的集合的重复 Enumerable,这种用法有点尴尬次,其中 n 是 T 的每个唯一组合中的元素数量,但它可以完成工作。结果的顺序对我来说并不重要,所以我没有转换稍后发布的“索引”版本。
这是我对扩展的使用,它对整数数组而不是字符串进行操作,并为我提供其中没有元素的“空”集和“完整”(或原始)集
In case it's of use to anyone else, I've converted the original C# extension Thomas Levesque posted to VB.NET:
It's a bit awkward usage to have to call Repeat n times to generate a repeated Enumerable containing the set of all possible values n times, where n is the number of elements in each resulting unique combination of T, but it gets the job done. Order of the results didn't matter for me, so I didn't convert the 'indexed' version posted later.
Here's my usage of the extension, which operates on an array of Integers instead of Strings, and gets me the 'empty' set with no elements in it and the 'full' (or original) set
我发现另一个 此处的方法(在此处查找 C# 代码)。
I found another approach here (look there for C# code).
一种简单的递归解决方案(大量列表创建开销):
一种使用链接 SO 算法的稍微不那么简单的迭代解决方案:
这些可能都可以得到改进,但根据所使用的集合的大小,其中一个应该足够高效。
A naive recursive solution (lots of list creation overhead):
A slightly less naive iterative solution using the linked SO algorithm:
These could probably both be improved, but depending on the size of the sets in use, one or the other should be efficient enough.
我不是用VB.NET编程的,这只是输入的。所以可能存在严重的错误。但这种方法应该有效。
I don't program in VB.NET, and this is just typed in. So there may be serious bugs. But the approach should work.
或者
or