Get all combinations of an array

前端 未结 4 721
时光说笑
时光说笑 2021-01-07 10:24

I\'m currently trying to make a function that gets all possible combinations of array values.

I have come up with a non function version but it\'s limited to 3 value

相关标签:
4条回答
  • 2021-01-07 11:00

    Here is my solution:

    function Remove ($element, $list)
    {
        $newList = @()
        $list | % { if ($_ -ne $element) { $newList += $_} }
    
        return $newList
    }
    
    
    function Append ($head, $tail)
    {
        if ($tail.Count -eq 0)
            { return ,$head }
    
        $result =  @()
    
        $tail | %{
            $newList = ,$head
            $_ | %{ $newList += $_ }
            $result += ,$newList
        }
    
        return $result
    }
    
    
    function Permute ($list)
    {
        if ($list.Count -eq 0)
            { return @() }
    
        $list | %{
            $permutations = Permute (Remove $_ $list)
            return Append $_ $permutations
        }
    }
    
    cls
    
    $list = "x", "y", "z", "t", "v"
    
    $permutations = Permute $list
    
    
    $permutations | %{
        Write-Host ([string]::Join(", ", $_))
    }
    

    EDIT: the same in one function (Permute). This is cheating a bit, however since I replaced plain functions whith lambdas. You could replace recursive calls with a stack you handle yourself, but that would make the code unecessarily complex ...

    function Permute ($list)
    {
        $global:remove = { 
            param ($element, $list) 
    
            $newList = @() 
            $list | % { if ($_ -ne $element) { $newList += $_} }  
    
            return $newList 
        }
    
        $global:append = {
            param ($head, $tail)
    
            if ($tail.Count -eq 0)
                { return ,$head }
    
            $result =  @()
    
            $tail | %{
                $newList = ,$head
                $_ | %{ $newList += $_ }
                $result += ,$newList
            }
    
            return $result
        }
    
        if ($list.Count -eq 0)
            { return @() }
    
        $list | %{
            $permutations = Permute ($remove.Invoke($_, $list))
            return $append.Invoke($_, $permutations)
        }
    }
    
    cls
    
    $list = "x", "y", "z", "t"
    
    $permutations = Permute $list
    
    $permutations | %{
        Write-Host ([string]::Join(", ", $_))
    }
    
    0 讨论(0)
  • 2021-01-07 11:04

    Here is my solution with a recursive function. It generates space separated strings but it's quite simple to split each element with $list[$i].split(" "):

    function Get-Permutations 
    {
        param ($array, $cur, $depth, $list)
    
        $depth ++
        for ($i = 0; $i -lt $array.Count; $i++)
        {
            $list += $cur+" "+$array[$i]        
    
            if ($depth -lt $array.Count)
            {
                $list = Get-Permutations $array ($cur+" "+$array[$i]) $depth $list
            }       
        }
    
        $list
    }    
    
    $array = @("first","second","third","fourth")
    $list = @()
    $list = Get-Permutations $array "" 0 $list
    
    $list
    
    0 讨论(0)
  • 2021-01-07 11:07

    I tried to learn something new and help you out but Im stuck. maybe this will help you get in the right direction but I dont know enough about Powershell recursion to figure this out. I converted the php to powershell and in theory it should work but it doesnt.

    $array = @('Alpha', 'Beta', 'Gamma', 'Sigma')
    
    
    function depth_picker([system.collections.arraylist]$arr,$temp_string, $collect)
    {
    if($temp_string -ne ""){$collect += $temp_string}
        for($i = 0; $i -lt $arr.count;$i++)
        {
        [system.collections.arraylist]$arrCopy = $arr
        $elem = $arrCopy[$i]
        $arrCopy.removeRange($i,1)
        if($arrCopy.count -gt 0){
        depth_picker -arr $arrCopy -temp_string "$temp_string $elem" -collect $collect}
        else{$collect += "$temp_string $elem"}
        }
    }
    $collect = @()
    depth_picker -arr $array -temp_string "" -collect $collect
    $collect
    

    It seems to work and will get you the first set of possibles:

    Alpha
    Alpha Beta
    Alpha Beta Gamma
    Alpha Beta Gamma Sigma
    

    But for some reason that I cant figure out when it gets back to the previous functions and does $i++ then checks ($i -lt $arr.count) $arr.count it always 0 so it never goes to the next iteration to continue finding the possibilities.

    Hopefully someone else can fix what I cant seem to figure out as I dont know enough about recursion. But it seems that with each level of depth called the previous depth level $arr variable and values is lost.

    0 讨论(0)
  • 2021-01-07 11:09

    The solution posted by Micky Balladelli almost worked for me. Here is a version that does not duplicate values:

    Function Get-Permutations 
    {
        param ($array_in, $current, $depth, $array_out)
        $depth++
        $array_in = $array_in | select -Unique
        for ($i = 0; $i -lt $array_in.Count; $i++)
        {
            $array_out += ($current+" "+$array_in[$i]).Trim()
            if ($depth -lt $array_in.Count)
            {
                $array_out = Get-Permutations $array_in ($current+" "+$array_in[$i]) $depth $array_out
            }
            else {}
        }
        if(!($array_out -contains ($array_in -Join " "))) {}
        for ($i = 0; $i -lt $array_out.Count; $i++)
        {
            $array_out[$i] = (($array_out[$i].Split(" ")) | select -Unique) -Join " "
        }
        $array_out | select -Unique
    }
    
    0 讨论(0)
提交回复
热议问题