【问题标题】:Passing Powershell Arrays by-reference not working as intended通过引用传递 Powershell 数组未按预期工作
【发布时间】:2018-08-05 19:12:39
【问题描述】:

引用数组

工作正常!

在 PowerShell 中通过引用传递数组的正常方法似乎工作正常:

Function Swap-Array ($theArray, $theArrayB, [int]$indexToSwap) {
  $temp = $theArrayA[$indexToSwap];
  $theArrayA[$indexToSwap] = $theArrayB[$indexToSwap];
  $theArrayB[$indexToSwap] = $temp;
} 

$a = @(1,2,3,4)
$b = @(3,2,4,1)
$a
$b
Swap-Array $a, $b, 2
$a
$b

输出:

a
-
1
2
3
4

b
-
3
2
4
1

a
-
1
2
4
3

b
-
3
2
3
1

问题

添加对象

当引用数组是一个非静态的 PSObjects 容器,并且我正在尝试添加新记录时,就会出现问题。修改现有记录好像没问题!

Function Swap-Apples($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Apples;
  $objectA[$indexToSwap].Apples = $objectB[$indexToSwap].Apples;
  $objectB[$indexToSwap].Apples = $temp;
}

Function Swap-Oranges($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Oranges;
  $objectA[$indexToSwap].Oranges = $objectB[$indexToSwap].Oranges;
  $objectB[$indexToSwap].Oranges = $temp;
}

<# heres the problematic bit #>
Function Add-Fruit ($object, [int]$howManyApples, [int]$howManyOranges) {
  $hAdd = @{
    Apples=$howManyApples
    Oranges=$howManyOranges
  }
  $hToAdd = New-Object -TypeName PSObject -Property $hAdd;
  $object += $hToAdd;
}

$a = @();
$b = @();
$a1 = @{
  Apples=3
  Oranges=2
}
$b1 = @{
  Apples=5
  Oranges=7
}
$a2 = @{
  Apples=6
  Oranges=3
}
$b2 = @{
  Apples=1
  Oranges=5
}
$aObject1 = New-Object -TypeName PSObject -Property $a1;
$bObject1 = New-Object -TypeName PSObject -Property $b1;
$aObject2 = New-Object -TypeName PSObject -Property $a2;
$bObject2 = New-Object -TypeName PSObject -Property $b2;
$a += $aObject1; $a += $aObject2;
$b += $bObject1; $b += $aObject2;

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Now lets make a trade`!";
Swap-Apples $a $b 0
Swap-Oranges $a $b 1

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Hey, I brought more fruit for A`!";
Add-Fruit -object $a -howManyApples 5 -howManyOranges 2

Write-Host "Values of A";
$a | Format-List

Write-Host "I brought more fruit for B too`!";
Add-Fruit -object $b -howManyApples 5 -howManyOranges 3

Write-Host "Values of B";
$b | Format-List

输出

Values of A


Oranges : 2
Apples  : 3

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 5

Oranges : 3
Apples  : 6



Now lets make a trade!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6



Hey, I brought more fruit for A!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6



I brought more fruit for B too!
Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6

Swap-ApplesSwap-Oranges 函数似乎工作正常。该程序在最后一段崩溃了,试图给 A 和 B 更多的果实!否则这通常会在本地范围内工作。我觉得这由于引用传递而分崩离析。

我将如何解决这个程序结束时的问题?

【问题讨论】:

  • 这不是错误。当您尝试将另一个项目添加到固定大小的数组时,会创建一个新数组
  • 我所说的错误是指“修复它”。抱歉,如果我的上下文有点错误,呵呵。如何声明一个可以更改大小并通过引用传递的数组?

标签: arrays powershell pass-by-reference psobject


【解决方案1】:

解决方案

动态数组列表

在 PowerShell 中,您可以创建固定大小和动态分配的数组。如果我想同时给 A 和 B 更多对象,我必须告诉 PowerShell 这是一个 ArrayList 而不是典型的标准 Array。

这意味着我不能像这样声明我的数组:

$a = @();
$b = @();

.NET 中的这种类型称为 System.Collections.ArrayList,可以在 PowerShell 程序中按引用传递,如下所示:

$a = New-Object -TypeName 'System.Collections.ArrayList';
$b = New-Object -TypeName 'System.Collections.ArrayList';

现在它不是固定大小的,所以我可以随意在我的程序中的任何地方添加记录,甚至是引用!

解决办法如下:

Function Swap-Apples($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Apples;
  $objectA[$indexToSwap].Apples = $objectB[$indexToSwap].Apples;
  $objectB[$indexToSwap].Apples = $temp;
}

Function Swap-Oranges($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Oranges;
  $objectA[$indexToSwap].Oranges = $objectB[$indexToSwap].Oranges;
  $objectB[$indexToSwap].Oranges = $temp;
}

<# ArrayList! #>
Function Add-Fruit ([System.Collections.ArrayList]$object, [int]$howManyApples, [int]$howManyOranges) {
  $hAdd = @{
    Apples=$howManyApples
    Oranges=$howManyOranges
  }
  $hToAdd = New-Object -TypeName PSObject -Property $hAdd;
  <# We have to call the ArrayList Add method to add to our dynamic object #>
  $object.Add($hToAdd);
}

$a = New-Object -TypeName 'System.Collections.ArrayList';
$b = New-Object -TypeName 'System.Collections.ArrayList';
$a1 = @{
  Apples=3
  Oranges=2
}
$b1 = @{
  Apples=5
  Oranges=7
}
$a2 = @{
  Apples=6
  Oranges=3
}
$b2 = @{
  Apples=1
  Oranges=5
}
$aObject1 = New-Object -TypeName PSObject -Property $a1;
$bObject1 = New-Object -TypeName PSObject -Property $b1;
$aObject2 = New-Object -TypeName PSObject -Property $a2;
$bObject2 = New-Object -TypeName PSObject -Property $b2;
<# Here we call the ArrayList Add method #>
$a.Add($aObject1); $a.Add($aObject2);
$b.Add($bObject1); $b.Add($aObject2);

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Now lets make a trade`!";
Swap-Apples $a $b 0
Swap-Oranges $a $b 1

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Hey, I brought more fruit for A`!";
Add-Fruit -object $a -howManyApples 5 -howManyOranges 2

Write-Host "Values of A";
$a | Format-List

Write-Host "I brought more fruit for B too`!";
Add-Fruit -object $b -howManyApples 5 -howManyOranges 3

Write-Host "Values of B";
$b | Format-List

以及(有点)预期的输出(见下文):

0
1
0
1
Values of A


Oranges : 2
Apples  : 3

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 5

Oranges : 3
Apples  : 6



Now lets make a trade!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6



Hey, I brought more fruit for A!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6

Oranges : 2
Apples  : 5



I brought more fruit for B too!
Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6

Oranges : 3
Apples  : 5

额外输出?

如果你在输出中观察到:

0
1
0
1

ArrayList 的 Add 方法返回你添加的记录的索引。由于它返回此值,因此它会从您的管道中退出到 Std-Out,因此请确保相应地引导它。

如果您的程序中不需要此输出,就像我在这里不需要的那样,请将其通过管道传输到 null 设备,如下所示:

$a.Add($aObject1) | Out-Null; $a.Add($aObject2) | Out-Null;
$b.Add($bObject1) | Out-Null; $b.Add($aObject2) | Out-Null;

这是最终的程序/输出:

代码:(Arraytest.ps1)

Function Swap-Apples($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Apples;
  $objectA[$indexToSwap].Apples = $objectB[$indexToSwap].Apples;
  $objectB[$indexToSwap].Apples = $temp;
}

Function Swap-Oranges($objectA, $objectB, $indexToSwap) {
  $temp = $objectA[$indexToSwap].Oranges;
  $objectA[$indexToSwap].Oranges = $objectB[$indexToSwap].Oranges;
  $objectB[$indexToSwap].Oranges = $temp;
}

<# ArrayList! #>
Function Add-Fruit ([System.Collections.ArrayList]$object, [int]$howManyApples, [int]$howManyOranges) {
  $hAdd = @{
    Apples=$howManyApples
    Oranges=$howManyOranges
  }
  $hToAdd = New-Object -TypeName PSObject -Property $hAdd;
  <# We have to call the ArrayList Add method to add to our dynamic object #>
  $object.Add($hToAdd) | Out-Null;
}

$a = New-Object -TypeName 'System.Collections.ArrayList';
$b = New-Object -TypeName 'System.Collections.ArrayList';
$a1 = @{
  Apples=3
  Oranges=2
}
$b1 = @{
  Apples=5
  Oranges=7
}
$a2 = @{
  Apples=6
  Oranges=3
}
$b2 = @{
  Apples=1
  Oranges=5
}
$aObject1 = New-Object -TypeName PSObject -Property $a1;
$bObject1 = New-Object -TypeName PSObject -Property $b1;
$aObject2 = New-Object -TypeName PSObject -Property $a2;
$bObject2 = New-Object -TypeName PSObject -Property $b2;
<# Here we call the ArrayList Add method #>
$a.Add($aObject1) | Out-Null; $a.Add($aObject2) | Out-Null;
$b.Add($bObject1) | Out-Null; $b.Add($aObject2) | Out-Null;

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Now lets make a trade`!";
Swap-Apples $a $b 0
Swap-Oranges $a $b 1

Write-Host "Values of A";
$a | Format-List

Write-Host "Values of B";
$b | Format-List

Write-Host "Hey, I brought more fruit for A`!";
Add-Fruit -object $a -howManyApples 5 -howManyOranges 2

Write-Host "Values of A";
$a | Format-List

Write-Host "I brought more fruit for B too`!";
Add-Fruit -object $b -howManyApples 5 -howManyOranges 3

Write-Host "Values of B";
$b | Format-List

输出:

Values of A


Oranges : 2
Apples  : 3

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 5

Oranges : 3
Apples  : 6



Now lets make a trade!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6



Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6



Hey, I brought more fruit for A!
Values of A


Oranges : 2
Apples  : 5

Oranges : 3
Apples  : 6

Oranges : 2
Apples  : 5



I brought more fruit for B too!
Values of B


Oranges : 7
Apples  : 3

Oranges : 3
Apples  : 6

Oranges : 3
Apples  : 5

【讨论】:

    【解决方案2】:

    对我有用:

    Function Swap-Array ($theArrayA, $theArrayB, [int]$indexToSwap) 
    {
      $temp = $theArrayA[$indexToSwap]
      $theArrayA[$indexToSwap] = $theArrayB[$indexToSwap]
      $theArrayB[$indexToSwap] = $temp
    } 
    
    $a = @(1,2,3,4)
    $b = @(3,2,4,1)
    $a
    $b
    Swap-Array $a $b 2
    $a
    $b
    

    只需删除昏迷。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-01
      • 1970-01-01
      相关资源
      最近更新 更多