2015-01-14 30 views
1

下面是一個簡單爲一套嵌套對於最高變量的值是1,2迴路,和3分別爲:嵌套for循環的抽象

for ($i = 0; $i -le 1; $i++) 
{ 
    for ($j = 0; $j -le 2; $j++) 
    { 
     for ($k = 0; $k -le 3; $k++) 
     { 
      "$i $j $k" 
     } 
    } 
} 

我想的抽象用於指示嵌套的任意數量for循環。因此,例如,上面會被調用,就像這樣:

NestedForLoops (1, 2, 3) { Param($i, $j, $k) "$i $j $k" } 

這裏是基於this answer一種方法:

function NestedForLoopsAux([int[]]$max_indices, [int[]]$indices, [int]$index, $func) 
{ 
    if ($max_indices.Count -eq 0) { &($func) $indices } 
    else 
    { 
     $rest = $max_indices | Select-Object -Skip 1 

     for ($indices[$index] = 0; $indices[$index] -le $max_indices[0]; $indices[$index]++) 
     { NestedForLoopsAux $rest $indices ($index + 1) $func } 
    } 
} 

function NestedForLoops([int[]]$max_indices, $func) 
{ 
    NestedForLoopsAux $max_indices (@(0) * $max_indices.Count) 0 $func 
} 

調用示例:

PS C:\> NestedForLoops (1, 2, 3) { Param([int[]]$indices); $i, $j, $k = $indices; "$i $j $k" } 
0 0 0 
0 0 1 
0 0 2 
0 0 3 
0 1 0 
0 1 1 
0 1 2 
0 1 3 
0 2 0 
0 2 1 
0 2 2 
0 2 3 
1 0 0 
1 0 1 
1 0 2 
1 0 3 
1 1 0 
1 1 1 
1 1 2 
1 1 3 
1 2 0 
1 2 1 
1 2 2 
1 2 3 

有沒有更好的辦法?

回答

1

我不知道這是否容易,但您可能會將其視爲爲您打開更多選項的一種方式。邏輯的核心是構建將使用Invoke-Expression執行的代碼字符串。大部分只是想看看我能否做到。

Function New-ForLoopBlock{ 
    Param(
     [char]$variableLetter, # {0} Index varialble 
     [int]$baseIndex,   # {1} Base Index Value 
     [int]$indexMaximum  # {2} Max Index Value 
    ) 
    "for (`${0} = {1}; `${0} -le {2}; `${0}++)" -f $variableLetter,$baseIndex,$indexMaximum 
} 


Function LoopDeLoop{ 
    Param(
     [int[]]$maximums, 
     [int]$baseIndex = 0 
    ) 

    # Build a small hashtable with variable and array values. 
    $values = @{} 
    For($letterIndex = 0; $letterIndex -lt $maximums.Count; $letterIndex++){ 
     New-Variable -Force -Name [char]($letterIndex + 65) 
     $values.([char]($letterIndex + 65)) = $maximums[$letterIndex] 
    } 

    $nestedLoops = "{}" 
    # Build the for loop 
    $nestedLoops = $values.GetEnumerator() | Sort-Object Name | ForEach-Object{ 
     "$(New-ForLoopBlock $_.Name $baseIndex $_.Value){" 
    } 

    # The output string this exists inside the loop 
    $outputString = [string]($values.GetEnumerator() | Sort-Object Name | ForEach-Object{"`$$($_.Name)"}) 

    # Add the output string and closing braces 
    $nestedLoops = "$nestedLoops`r`n`"$outputString`"`r`n$("}" * $maximums.Count)" 

    Invoke-Expression $nestedLoops 
} 

LoopDeLoop需要2個參數。就像你的一個整數數組和一個可選的基值。爲$maximums中的每個數組元素創建一些變量(形式爲$ a,$ b,...),它們將表示每個for循環的索引值。

字符串$nestedLoops然後使用New-ForLoopBlock的輸出創建字符串。它不需要是一個函數,但它只是返回一個具有for循環語句的字符串。在之前的迭代中,更多的邏輯在那裏。

然後我們需要構建小輸出字符串。在你的例子中,這是「$ i $ j $ k」。我的建立是基於創建了多少個變量。

字符串結束時,我們用尾部大括號關閉for循環。什麼$nestedloops示例如下:

for ($A = 2; $A -le 3; $A++){ for ($B = 2; $B -le 3; $B++){ for ($C = 2; $C -le 4; $C++){ 
"$A $B $C" 
}}} 

不妙就格式而言,但代碼是100%的功能。現在,讓我們只是看一些樣本輸出功能:

LoopDeLoop (3,3,4) 2 
2 2 2 
2 2 3 
2 2 4 
2 3 2 
2 3 3 
2 3 4 
3 2 2 
3 2 3 
3 2 4 
3 3 2 
3 3 3 
3 3 4 
+0

元編程爲贏! :-)有趣的做法! – dharmatech