Декартово произведение, написанное с помощью Powershell - PullRequest
0 голосов
/ 25 ноября 2010

Я застрял, пытаясь завершить алгоритм декартового произведения в Powershell. Используя части других формул, найденных здесь в stackoverflow, я пришел к следующему:

clear

Function New-GenericDictionary([type] $keyType, [type]$valueType)
{
    $base = [System.Collections.Generic.Dictionary``2]
    $ct = $base.MakeGenericType(($keyType, $valueType))
    New-Object $ct
}

$sets = New-GenericDictionary int string
$sets[0] = "1"
$sets[1] = "0,1"
$sets[2] = "0,1"

$iterations = 1
$stringCombo = ""
foreach($key in $sets.Keys) {
    $pieces = $sets[$key].Split(",")
    $iterations = $iterations * $pieces.Length
}

for ($i = 0; $i -lt $iterations; $i++) {
    $stringCombo = ""
    foreach($key in $sets.Keys) {
        $pieces = $sets[$key].Split(",")
        $val = $pieces.Length
        $get = $i%$val
        $stringCombo = $stringCombo + " " + $pieces[$get]
    }

    Write-Host $stringCombo.Trim()
}

#output hoped for:
#1 0 0
#1 0 1
#1 1 0
#1 1 1

#output is:
#1 0 0
#1 1 1
#1 0 0
#1 1 1

Как видно в комментариях внизу фрагмента кода, вывод не совсем дает желаемые результаты. Счетчик итераций возвращает правильное значение, но комбинации не завершаются правильно.

В этом фрагменте $ sets [x] исправлено, но в реальном скрипте $ словарь устанавливает наборы элементов как часть цикла и может содержать от 1 до многих элементов за итерацию.

Может кто-нибудь предложить второй набор глаз, чтобы показать мне, что я пропустил?

Спасибо

Ответы [ 5 ]

1 голос
/ 14 мая 2015

Моя попытка сработала достаточно хорошо для моих нужд:

function Get-CartesianProduct {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [object[]] $List1,
        [Parameter(Mandatory = $true)]
        [object[]] $List2)
    process {
        $List1 |
            %{
                $Item1 = $_

                $List2 |
                    %{
                        $Item2 = $_

                        @{
                            Item1 = $Item1
                            Item2 = $Item2
                        }
                    }
            }
    }
}

Get-CartesianProduct 'Apple','Rhubarb','Chocolate' 'Pie','Cake' |
    %{
        write-host $_.Item1 $_.Item2
    }
1 голос
/ 20 марта 2013

Я хотел, чтобы один вкладыш получал каждую уникальную комбинацию. Например, с a, b, c вы получите а, б а, с б, с

Вот что я придумал

function pairwise($list) { $i = 0; $list | % { foreach ($li in ($list | select -Skip (++$i))) { new-object PSObject -Property @{Left=$_;Right=$li} } } }
1 голос
/ 27 ноября 2010

Я не думаю, что вам нужны общие словари для этого.Простая пара массивов будет делать:

PS> $c1 = 0,1
PS> $c2 = 0,1
PS> foreach ($i in $c1) {
>>    foreach ($j in $c2) {
>>      "$i,$j"
>>    }
>>  }
>>
0,0
0,1
1,0
1,1
0 голосов
/ 30 мая 2012

Улучшенная версия

# ------------------------------------------------------------------------------
<#

    CartesianProduct-Lists

#>
# ------------------------------------------------------------------------------

function CartesianProduct-Lists
{
    param
    (
        $Lists
    )

    function Make-List
    {
        param
        (
            $Head, $Tail
        )

        if ($Tail -is [Object[]])
        {
            # List already so just extend
            $Result = ,$Head + $Tail
        }
        else
        {
            # Create List
            $Result = @($Head, $Tail)
        }

        ,$Result
    }

    switch (,$Lists) {
        $Null 
        { 
            break 
        }

        # 1 List so just return it
        { $_.Count -eq 1 } 
        { 
            $_ 
        }

        # More than one list so recurse
        { $_.Count -gt 1 } 
        {  
            $Head = $_[0]
            $Index = $_.Count - 1
            $Tail = $_[1..$Index]

            $Next = CartesianProduct-Lists $Tail

            $Result = @()

            foreach ($HeadItem in $Head)
            {
                foreach ($NextItem in $Next)
                {            
                    $Result += ,(Make-List $HeadItem $NextItem)
                }
            }

            ,$Result
        }
    }    
}
0 голосов
/ 20 апреля 2012

Не красиво, но делает трюк для n списков

# ------------------------------------------------------------------------------
<#

    CartesianProduct-Lists

#>
# ------------------------------------------------------------------------------

function CartesianProduct-Lists
{
    param
    (
        $Lists
    )

    function Make-List
    {
        param
        (
            $Head, $Tail
        )

        if ($Head -is [Object[]])
        {
            # List already so just extend
            $Result = $Head + $Tail
        }
        else
        {
            # Create List
            $Result = @($Head, $Tail)
        }

        ,$Result
    }

    # if Head..Tail 
    if (@($Lists).Count -gt 1)
    {
        $Head = $Lists[0]
        $Next = $Lists[1]

        $Result = @()
        foreach ($HeadItem in $Head)
        {
            foreach ($NextItem in $Next)
            {            
                $Result += ,(Make-List $HeadItem $NextItem)
            }
        }

        if (@($Lists).Count -gt 2)
        {
            $Index = $Lists.Count - 1
            $Tail = $Lists[2..$Index]

            $Result = ,$Result + $Tail

            $Result = CartesianProduct-Lists $Result
        }

        ,$Result
    }
}

# --------------------------------------------------------

$Lists = @(@(1),@(0,1),@(0,1))

$Result = CartesianProduct-Lists $Lists

$Result | % { $_; "" }

Урожайность

1 0 0

1 0 1

1 1 0

1 1 1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...