2011-03-28 133 views
3

我正在編寫一些代碼,以瞭解如何將值列表分割成更易於管理的塊。我想這樣做的原因是因爲我將擁有大約10萬個實時值,並且我想盡量減少失敗風險。分割值列表


$wholeList = 1..100 

$nextStartingPoint 

$workingList 

function Get-NextTenItems() 
{ 
    $workingList = (1+$nextStartingPoint)..(10+$nextStartingPoint) 

    $nextStartingPoint += 10 

    Write-Host "inside Get-NextTenItems" 
    write-host "Next StartingPoint: $nextStartingPoint" 
    $workingList 
    Write-Host "exiting Get-NextTenItems" 
} 

function Write-ListItems() 
{ 
    foreach ($li in $workingList) 
    { 
     Write-Host $li 
    } 
} 
Get-NextTenItems 
Write-ListItems 
Get-NextTenItems 
Write-ListItems 

我跑在調試器的PowerGUI的代碼和我注意到我的$ nextStartingPoint被重置爲0,當我退出獲取-NextTenItems功能。

爲什麼會發生這種情況,我該如何預防它?

我是否還應該假設$ workingList發生了同樣的事情?

回答

2

在您的示例中,Get-NextTenItems更改其本地變量。有幾種方法可以解決這個問題,這裏有兩個:

1)明確指定變量範圍(使用前綴scriptglobal)。也就是說,使用那個變量作爲$script:nextStartingPoint,$script:workingList裏面的函數。

2)更改其呼叫的功能範圍。即,使用點運算符(「dot-source」函數)調用函數,即在當前範圍內執行它。此代碼工作正常(無其他變化需要):

. Get-NextTenItems 
Write-ListItems 
. Get-NextTenItems 
Write-ListItems 

又見

help about_scopes 
1

前面的答案是確定。但它不完整,它讓你編碼不可讀。從純粹的編程角度來看,您有兩種其他方式將參數傳遞給過程(或函數),其中一種方式允許您修改參數。

使用這種方式,您記錄您的功能

Function addition ([int]$x, [int]$y) { 
    $x + $y 
} 

2.參數通過參數的參數1.參數按值(常見的方式)

(參照一種指針稱爲)

使用這種方法,最後一個參數可以修改爲你的函數。

function addition ([int]$x, [int]$y, [ref]$R) { 
$Res = $x * $y 
$R.value = $Res 
} 

# usage 
addition $A $B ([ref]$C) 

在使用第二個解決您的代碼:

  1. 允許您修改變量到函數
  2. 我們知道該功能的其他讀者,這個函數是能夠修改一個她的參數

我希望它有幫助。

+0

@JP - 感謝您的建議。這可能比我想要的複雜一點。這是一個單獨使用的腳本,看起來更像是一個C#的想法。另外,在用C#編程時,我傾向於反對通過ref傳遞項目,因爲它們打開了產生副作用的方式(一種功能性編程思想,這被認爲是不可取的)。 – Mike 2011-03-28 23:34:20

3

我的建議是使用管道。一個函數產生塊,另一個函數消耗它們。

使用這種方法,您不需要污染全局/腳本範圍,這不是一個好主意。所需要的一切都保存在需要它的功能中。

function Get-Chunk 
{ 
    param(
     [Parameter(Mandatory=$true)]$collection, 
     [Parameter(Mandatory=$false)]$count=10 
    ) 
    #temporary array 
    $tmp = @() 
    $i = 0 
    foreach($c in $collection) { 
     $tmp += $c     # add item $c to array 
     $i++      # increase counter; indicates that we reached chunk size 
     if ($i -eq $count) { 
      ,$tmp     # send the temporary array to the pipeline 
      $i = 0     # reset variables 
      $tmp = @()   
     } 
    } 
    if ($tmp) {     # if there is something remaining, send it to the pipeline 
     ,$tmp 
    } 
} 

function Write-ListItems 
{ 
    param(
     [Parameter(Mandatory=$true, ValueFromPipeline=$true)]$chunk 
    ) 
    process { 
     write-host Chunk: "$chunk" 
    } 
} 

測試功能:

$wholeList = 1..100 
Get-Chunk $wholeList | Write-ListItems 
Chunk: 1 2 3 4 5 6 7 8 9 10 
Chunk: 11 12 13 14 15 16 17 18 19 20 
Chunk: 21 22 23 24 25 26 27 28 29 30 
Chunk: 31 32 33 34 35 36 37 38 39 40 
Chunk: 41 42 43 44 45 46 47 48 49 50 
Chunk: 51 52 53 54 55 56 57 58 59 60 
Chunk: 61 62 63 64 65 66 67 68 69 70 
Chunk: 71 72 73 74 75 76 77 78 79 80 
Chunk: 81 82 83 84 85 86 87 88 89 90 
Chunk: 91 92 93 94 95 96 97 98 99 100 

Get-Chunk $wholeList 32 | Write-ListItems 
Chunk: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 
Chunk: 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 
Chunk: 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 
Chunk: 97 98 99 100 

更新

我添加了一些意見,以澄清事情了。請注意,發送內容到流水線時(a)我不使用return,因爲我會從功能中跳出去。 (b)開始時的逗號將$tmp的內容包裝爲數組,因此它會創建帶有一個項目的新數組(這是N個項目的數組)。爲什麼?因爲在PowerShell中有自動展開的功能,它會從數組中展開項目並將所有項目展平 - >結果將再次成爲一個大數組。

例子:

function Get-Arrays { 
    1,2,3 
    "a", "b" 
    ,(get-date) 
    4,5,6 
} 
Get-Arrays | % { "$_" } 

這按預期工作:

function Get-Arrays { 
    ,(1,2,3) 
    ,("a", "b") 
    ,(get-date) 
    ,(4,5,6) 
} 
Get-Arrays | % { "$_" } 
+0

感謝您添加此。我的PowerShell技能並非如此,我想使用param關鍵字。我沒有想到參數化在這個範圍內,因爲這個腳本是爲單一目的而存在的,儘管我開始認爲Get-Chunk函數可以偶爾重用。而且你的封裝比我的封裝好,儘管我不確定是什麼,@ tmp是 - 我可以找到的東西。 – Mike 2011-03-28 23:43:57

+0

添加了一些評論和信息,它可能有幫助.. – stej 2011-03-28 23:59:24

+0

...我以爲我已經開始在Powershell行動了......你已經把我撞倒在地了。 ;-) – Mike 2011-03-29 00:08:20