각각

2015-01-14 4 views
1

여기서 최대 변수 값은 1, 2이다 루프 중첩의 세트에 대해 간단 추상화 3 :각각

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

는 I 중첩 임의의 수를 나타내는 추상화를하려는 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, ... 형태로)를 만듭니다.

$nestedLoops 문자열은 New-ForLoopBlock의 출력으로 생성됩니다. 함수 일 필요는 없지만 for 루프 문이있는 문자열 만 반환합니다. 초기 반복에서는 더 많은 논리가있었습니다.

그러면 작은 출력 문자열을 만들어야합니다. 귀하의 예에서 이것은 "$ i $ j $ k"입니다. 광산은 얼마나 많은 변수가 만들어 졌는지에 따라 만들어졌습니다.

문자열의 끝 부분은 중괄호가있는 for 루프를 닫습니다.

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 % 작동 : 같은 것을 $nestedloops의 예를 보인다. 이제 함수의 출력 샘플을 살펴 보겠습니다.

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