将值返回到数组时出错

时间:2016-06-07 14:41:46

标签: arrays powershell

我尝试创建一个简单的优化脚本。这是我的代码:

# Analysis gives the initial inputs and outputs
$initialinputs  
$initialoutputs 

# The objective function
$F = ([math]::pow($initialinputs, 2)) * 2 - 3* $initialinputs
# Differentiation of the objective function
$DF = 2 * $initialinputs - 3
$ScaleFactor = 0.2

# If the optimum solution has been obtained, two termination measurements:
# maximum iteration and termination criterion(gradient)
$Maxloop = 100
$Termi = 0.001

# Create arrays
$InputsArr = @() #The array of inputs
$FunctionArr = @() #The array of function values
$DFunctionArr = @() # The array of differentiation values (Gradient)

# Calculations
#$InputsArr[0] = $initialinputs  #The first input
#$FunctionArr[0] = $F[$InputsArr[0]]
#$DFunctionArr[0] = $DF[$inputsArr[0]]

for ($Innerloop = 1; $Innerloop -le $Maxloop; $Innerloop++)
{
     # Calculate the second input
     $InputsArr[$innerloop] = $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3)

     $initialinputs = $InputsArr[$Innerloop]

     # Calculate the function value
     $FunctionArr[$innerloop] = ([math]::pow($initialinputs, 2)) * 2 - 3 * $initialinputs
     Return, $FunctionArr

     # Calculate the gradient value
     $DFunctionArr[$innerloop] = 2 * $initialinputs - 3
     return, $DFunctionArr

     # If the gradient value less than the termination criterion (gradient),
     # break the loop
     if ($DFunctionArr[$innerloop] -le $Termi)
     {
         break
     }
}

我创建了空数组,然后使用for循环进行优化并将输出存储在数组中。但我得到了一些错误,如下所示:

ERROR: +     $InputsArr[$Innerloop] = $initialinputs
ERROR: +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR:     + CategoryInfo          : OperationStopped: (:) [], IndexOutOfRangeException
ERROR:     + FullyQualifiedErrorId : System.IndexOutOfRangeException

ERROR: +     $FunctionArr[$innerloop] = $Functionoutput
ERROR: +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ERROR:     + CategoryInfo          : OperationStopped: (:) [], IndexOutOfRangeException
ERROR:     + FullyQualifiedErrorId : System.IndexOutOfRangeException

我不太清楚如何修复错误。如何将值返回到数组? +=是唯一的方法吗?我现在对阵列感到困惑。

2 个答案:

答案 0 :(得分:1)

初始化这样的数组:$InputsArr = @()时,powershell会创建一个长度为0的数组。因此,当您尝试使用$InputsArr[$innerloop]对此数组进行寻址时,会抛出元素$innerloop的错误不存在。

两种解决方案。您可以显式初始化特定类型和长度的数组:

$InputsArr = New-Object double[] $MaxLoop

或者,您可以在代码中使用+=运算符向数组添加新值:

$InputsArr += $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input

+=创建一个长度为n + 1的新数组,复制旧数组,然后添加新值,因此对于大型数组效率非常低。请参阅here

答案 1 :(得分:0)

@()定义的PowerShell数组是动态调整大小的。除非实际包含元素,否则您无法对其中的内容进行索引访问。这就是为什么你得到"索引越界"在$array[$index]循环中使用for时出现异常。该数组还没有字段$index

基本上有两种方法可以填充PowerShell数组:

  • 在循环中附加到现有数组:

    $array = @()
    for (...) {
      $array += $foo
    }
    
  • 回显循环内的元素并将循环输出分配给变量:

    $array = for (...) {
      $foo
    }
    

对于大量的数组元素应避免使用前者,因为每个追加操作(+=)将创建一个大小增加的新数组,复制元素,然后将新数组分配给变量。后一种方法在性能方面要优越得多。后一种方法的唯一缺点是,除非循环产生至少两个元素,否则结果不会是一个数组。您可以通过强制执行数组输出来缓解此问题:@(for (...) {...})

PowerShell还允许您创建固定大小的数组:

$size  = 100
$array = New-Object Object[] $size

然而,这样做通常没有优势。

另请注意,循环中的第一条指令假定数组已包含初始值:

$InputsArr[$innerloop] = $InputsArr[$Innerloop - 1] - $ScaleFactor * (2 * $InputsArr[$Innerloop - 1] - 3) #Calculate the second input

因此你需要在开始循环之前用一个元素预填充数组:

$InputsArr = @($initialValue)

据说,有更多的PoSh方法用数值填充数组,例如:像这样:

$i = $initialValue
$array = @($i)
$array += 1..$Maxloop | ForEach-Object {
  $i -= $ScaleFactor * (2 * $i - 3)
  $i
}

如果你想在同一个循环中填充多个数组(因为出于某种原因你不能为每个数组使用一个循环),附加可能是你最好的选择。像这样:

$InputsArr    = @($initialinputs)
$FunctionArr  = @($initialinputs)
$DFunctionArr = @($initialinputs)
for ($i = 1; $i -le $Maxloop -and $DFunctionsArr[-1] -le $Termi; $i++) {
    $InputsArr    += $InputsArr[-1] - $ScaleFactor * (2 * $InputsArr[-1] - 3)
    $FunctionArr  += ([Math]::Pow($InputsArr[-1], 2)) * 2 - 3 * $InputsArr[-1]
    $DFunctionArr += 2 * $InputsArr[-1] - 3
}

或者像这样,如果您以后不需要$InputsArr

$FunctionArr  = @($initialinputs)
$DFunctionArr = @($initialinputs)
$v = $initialinputs
for ($i = 1; $i -le $Maxloop -and $DFunctionsArr[-1] -le $Termi; $i++) {
    $v -= $ScaleFactor * (2 * $v - 3)

    $FunctionArr  += [Math]::Pow($v, 2) * 2 - 3 * $v
    $DFunctionArr += 2 * $v - 3
}