这个问题包含VB.NET代码,但我可以接受C#中解释的解决方案。
过去,在StackOverflow帮助用户的帮助下,我构建了这个函数,用于排列字符:
<DebuggerStepThrough>
Public Shared Function PermuteCharacters(ByVal charSet As IEnumerable(Of Char),
ByVal length As Integer,
ByVal allowRepetition As Boolean) As IEnumerable(Of String)
If (charSet.Count <> charSet.Distinct.Count) Then
Throw New ArgumentException("Char-set contains duplicated characters.", "charSet")
Return Nothing
End If
If (length = 1) Then
Return charSet.Select(Function(c As Char)
Return New String(New Char() {c})
End Function)
End If
If (allowRepetition) Then
Return PermuteCharacters(charSet:=charSet, length:=length - 1, allowRepetition:=True).
SelectMany(Function(str As String)
Return charSet
End Function,
Function(str As String, c As Char)
Return str & c
End Function)
Else
Return PermuteCharacters(charSet:=charSet, length:=length - 1, allowRepetition:=False).
SelectMany(Function(x As String) charSet,
Function(str As String, c As Char)
If Not str.Contains(c) Then
Return str & c
Else
Return Nothing
End If
End Function).
Where(Function(value As String) value IsNot Nothing)
End If
End Function
现在,在C#或Vb.Net中,我想要排列集合元素之间的所有可能组合(只有数字类型或字符串的集合)。
这是我到目前为止所做的,它是不完整的,并没有给我预期的结果:
Public Shared Function PermuteItems(ByVal items As IEnumerable(Of String)) As IEnumerable(Of IEnumerable(Of String))
Return items.SelectMany(
Function(x As String) As IEnumerable(Of String)
Return items
End Function,
Function(str1 As String, str2 As String) As IEnumerable(Of String)
Return {str1}.Concat({str2})
End Function)
End Function
Public Shared Function PermuteItems(ByVal items As IEnumerable(Of Integer)) As IEnumerable(Of IEnumerable(Of String))
Return PermuteItems((From item As Integer In items Select Convert.ToString(item)))
End Function
我需要帮助来修复我得到的结果值,我只收集了两个元素的集合。
对我来说保留 LINQ-to-Object 方法非常重要。
C#online(和未经测试的)翻译:
public static IEnumerable<IEnumerable<string>> PermuteItems(IEnumerable<string> items) {
return items.SelectMany((string x) => { return items; }, (string str1, string str2) => { return { str1 }.Concat({ str2 }); });
}
public static IEnumerable<IEnumerable<string>> PermuteItems(IEnumerable<int> items) {
return PermuteItems((from item in itemsConvert.ToString(item)));
}
//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================
如果我将数组传递给包含这些元素的函数: {10,2,30} ,那么它应该返回一个包含这些集合的IEnumerable(Of IEnumerable(Of Integer))
:
如果我将数组传递给包含这些元素的函数: {&#34; abc&#34;,&#34;&#34;,&#34; abc&#34;} 然后它应该返回一个包含这些集合的IEnumerable(Of IEnumerable(Of String))
:
元素可以是等号,集合不是。
顺序很重要,但我明白这是一个不同的问题,我认为我可以通过LINQ分组或排序来解决这个问题。
答案 0 :(得分:2)
这对我有用:
public IEnumerable<IEnumerable<T>> Permutate<T>(IEnumerable<T> source)
{
var xs = source.ToArray();
return
xs.Length == 1
? new [] { xs }
: (
from n in Enumerable.Range(0, xs.Length)
let cs = xs.Skip(n).Take(1)
let dss = Permutate<T>(xs.Take(n).Concat(xs.Skip(n + 1)))
from ds in dss
select cs.Concat(ds)
).Distinct(new EnumerableEqualityComparer<T>());
}
private class EnumerableEqualityComparer<T> : IEqualityComparer<IEnumerable<T>>
{
public bool Equals(IEnumerable<T> a, IEnumerable<T> b)
{
return a.SequenceEqual(b);
}
public int GetHashCode(IEnumerable<T> t)
{
return t.Take(1).Aggregate(0, (a, x) => a ^ x.GetHashCode());
}
}
var source = new[] { 10, 2, 30 };
我得到:
{10, 2, 30}
{10, 30, 2}
{2, 10, 30}
{2, 30, 10}
{30, 10, 2}
{30, 2, 10}
我得到var source = new[] { "abc", "", "abc" };
:
{"abc", "", "abc"}
{"abc", "abc", ""}
{"", "abc", "abc"}
Vb.Net等价物:
Public Function Permutate(Of T)(source As IEnumerable(Of T)) As IEnumerable(Of IEnumerable(Of T))
Dim xs As T() = source.ToArray()
Return If(xs.Length = 1,
{xs},
(From n In Enumerable.Range(0, xs.Length)
Let cs = xs.Skip(n).Take(1)
Let dss = Permutate(Of T)(xs.Take(n).Concat(xs.Skip(n + 1)))
From ds In dss Select cs.Concat(ds))
).Distinct(New EnumerableEqualityComparer(Of T)())
End Function
Public Class EnumerableEqualityComparer(Of T) : Implements IEqualityComparer(Of IEnumerable(Of T))
Public Shadows Function Equals(a As IEnumerable(Of T), b As IEnumerable(Of T)) As Boolean _
Implements IEqualityComparer(Of IEnumerable(Of T)).Equals
Return a.SequenceEqual(b)
End Function
Public Shadows Function GetHashCode(t As IEnumerable(Of T)) As Integer Implements _
IEqualityComparer(Of IEnumerable(Of T)).GetHashCode
Return t.Take(1).Aggregate(0, Function(a, x) a Xor x.GetHashCode())
End Function
End Class
答案 1 :(得分:2)
查看Combinatorics - 一个nuget包(和source code)来计算排列和组合。
答案 2 :(得分:0)
不确定性能。但紧凑
var permutation = list.SelectMany((item,i) => list.Skip(i + 1).Select((another) => (item, another)));