我正在尝试找出从PowerShell数组获得独特组合的最佳方法。例如,我的数组可能是
@(B,C,D,E)
我希望得到这样的输出:
B
C
D
E
B,C
B,D
B,E
C,D
C,E
D,E
B,C,D
C,D,E
B,C,D,E
我不想重新安排组合。如果组合C,D已经存在,那么我不想要组合D,C。这对我来说是多余的。
我查看了这里的功能:Get all combinations of an array
但他们不是我想要的。我一直在努力解决这个问题,但是花了很多时间没有成功。我以为我会在这里问这个问题,如果其他人已经知道我不是在浪费时间。
谢谢!
答案 0 :(得分:3)
这是对我所采用的C#类的解决方案的改编,它提出了同样的问题。对于任何集合,查找所有子集,包括空集。
function Get-Subsets ($a){
#uncomment following to ensure only unique inputs are parsed
#e.g. 'B','C','D','E','E' would become 'B','C','D','E'
#$a = $a | Select-Object -Unique
#create an array to store output
$l = @()
#for any set of length n the maximum number of subsets is 2^n
for ($i = 0; $i -lt [Math]::Pow(2,$a.Length); $i++)
{
#temporary array to hold output
[string[]]$out = New-Object string[] $a.length
#iterate through each element
for ($j = 0; $j -lt $a.Length; $j++)
{
#start at the end of the array take elements, work your way towards the front
if (($i -band (1 -shl ($a.Length - $j - 1))) -ne 0)
{
#store the subset in a temp array
$out[$j] = $a[$j]
}
}
#stick subset into an array
$l += -join $out
}
#group the subsets by length, iterate through them and sort
$l | Group-Object -Property Length | %{$_.Group | sort}
}
像这样使用:
PS C:>Get-Subsets @('b','c','d','e')
b
c
d
e
bc
bd
be
cd
ce
de
bcd
bce
bde
cde
bcde
请注意,计算成本会随着输入数组的长度呈指数增长。
Elements SecondstoComplete
15 46.3488228
14 13.4836299
13 3.6316713
12 1.2542701
11 0.4472637
10 0.1942997
9 0.0867832
答案 1 :(得分:2)
我厌倦了这一点。我确实设法让它产生预期的结果,但它是如何做到的并不那么优雅。使用递归功能。
Function Get-Permutations{
Param(
$theInput
)
$theInput | ForEach-Object{
$element = $_
$sansElement = ($theInput | Where-Object{$_ -ne $element})
If($sansElement.Count -gt 1){
# Build a collection of permutations using the remaining elements that were not isolated in this pass.
# Use the single element since it is a valid permutation
$perms = ,$element
For($elementIndex = 0;$elementIndex -le ($sansElement.Count - 1);$elementIndex++){
$perms += ,@(,$element + $sansElement[0..$elementIndex] | sort-object)
}
# For loop does not send to output properly so that is the purpose of collecting the results of this pass in $perms
$perms
# If there are more than 2 elements in $sansElement then we need to be sure they are accounted for
If($sansElement -gt 2){Get-Permutations $sansElement}
}
}
}
Get-Permutations B,C,D,E | %{$_ -join ","} | Sort-Object -Unique
我希望我能清楚地解释一下......所以函数的每次传递都会采用一个数组。该数组的每个单独元素将与数组的其余部分隔离,该部分由变量$element
和$sansElement
表示。
使用这些变量,我们构建了由这些元素组成的单个且逐渐变大的数组。让此示例显示使用数组1,2,3,4
1
1,2
1,2,3
1,2,3,4
以上是针对每个“数字”进行的
2
2,1
2,1,3
2,1,3,4
等等。如果返回的数组包含的元素多于两个(1,2
与示例中的2,1
相同,所以我们不关心超出一个匹配的对)我们将采用该数组并通过功能相同。
真正的问题是这里的逻辑(我知道这可能很难吞下)会产生几个副本。我想你可以创建一个哈希表,我将探索它,但它不会消除逻辑缺陷。
只要你没有成千上万的元素,无论我打败自己,这个过程都会产生结果。
Get-Permutations
将返回数组数组。 PowerShell会在每行显示一个元素。你要求逗号分隔输出,-join
进来。Sort-Object -Unique
将那些排序后的字符串丢弃重复项。
示例输出
B
B,C
B,C,D
B,C,D,E
B,C,E #< Missing from your example output.
B,D
B,D,E #< Missing from your example output.
B,E
C
C,D
C,D,E
C,E
D
E