2011-03-28 91 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