【问题标题】:Return array with single element in PowerShell在 PowerShell 中返回具有单个元素的数组
【发布时间】:2017-06-19 06:34:00
【问题描述】:

这应该很简单——我需要从一个函数返回一个哈希表数组。这在有多个哈希表时有效,但当只有一个时,结果不是数组。我宁愿不测试结果是否为数组。

function GetArrayWith1Hashtable()
{
    $array = @()

    $hashtable = @{}
    $hashtable["a"] = "a" 
    $hashtable["b"] = "b" 
    $hashtable["c"] = "c"
    $array += $hashtable 

    Write-Host "GetArrayWith1Hashtable array.Length =" $array.Length
    Write-Host "GetArrayWith1Hashtable array.Count" $array.Count
    Write-Host "GetArrayWith1Hashtable array[0].Keys" $array[0].Keys

    $array
}

function GetArrayWith2Hashtables()
{
    $array = @()

    $hashtable = @{}
    $hashtable["a"] = "a" 
    $hashtable["b"] = "b" 
    $hashtable["c"] = "c"
    $array += $hashtable 

    $hashtable2 = @{}
    $hashtable2["d"] = "d" 
    $hashtable2["e"] = "e"
    $hashtable2["f"] = "f"
    $array += $hashtable2 

    Write-Host "GetArrayWith2Hashtables array.Length = " $array.Length
    Write-Host "GetArrayWith2Hashtables array.Count = " $array.Count
    Write-Host "GetArrayWith2Hashtables array[0].Keys =" $array[0].Keys
    Write-Host "GetArrayWith2Hashtables array.Count = "$array[1].Keys

    $array
}

$result1 = GetArrayWith1Hashtable
# $result1.Length - not available
Write-Host "Result of GetArrayWith1Hashtable result1.Count = " $result1.Count                      # Count = 2 (would expect this to be 1)
# $result1[0] not available - not an array

$result2 = GetArrayWith2Hashtables
Write-Host "Result of GetArrayWith2Hashtables result2.Length = "    $result2.Length # Length = 2
Write-Host "Result of GetArrayWith2Hashtables result2.Count = "     $result2.Count # Count = 2
Write-Host "Result of GetArrayWith2Hashtables result2[0].Keys = "     $result2[0].Keys # Keys = c a b
Write-Host "Result of GetArrayWith2Hashtables result2[1].Keys = "     $result2[1].Keys # Keys = d e f

 <#
  FULL OUTPUT:

 GetArrayWith1Hashtable array.Length = 1
 GetArrayWith1Hashtable array.Count 1
 GetArrayWith1Hashtable array[0].Keys c a b

 Result of GetArrayWith1Hashtable result1.Count =  2

 GetArrayWith2Hashtables array.Length =  2
 GetArrayWith2Hashtables array.Count =  2
 GetArrayWith2Hashtables array[0].Keys = c a b
 GetArrayWith2Hashtables array.Count =  d e f

 Result of GetArrayWith2Hashtables result2.Length =  2
 Result of GetArrayWith2Hashtables result2.Count =  2
 Result of GetArrayWith2Hashtables result2[0].Keys =  c a b
 Result of GetArrayWith2Hashtables result2[1].Keys =  d e f

 #>

【问题讨论】:

    标签: arrays powershell hashtable powershell-5.0


    【解决方案1】:

    只需将返回类型转换为数组即可:

    $result1 = @(GetArrayWith1Hashtable)
    

    【讨论】:

    • 这不是强制转换,这不是您转换为类型的方式。您在这里所做的是将结果添加到一个全新的数组中,可能会将一个数组添加到一个数组中。
    • 确实不是演员,@JohnC,而是@() 的应用程序array-subexpression operator。但是,对于一个函数一个一个地发出其输出对象的方法来说,它是一个有效的解决方案,正如问题中那样,凭借 PowerShell 对输出对象的自动枚举。可以说让 调用者 确保某物是一个数组会更好,如此处所示,因为发出数组作为单个对象 的函数在管道中不会按预期工作。
    • @mklement0 你假设太多了。并非所有编写的函数都旨在通过管道传输。 op 想要将数组作为单个对象返回。正如我已经明确指出的那样,这个示例可能会在数组中返回一个数组。如果他们要遵循您所指的与管道一起正常工作的内容,那么所有这些示例都是不正确的,它们应该只为每个项目调用 write-object 而不是一次全部返回一个数组。
    • @JohnC:是的,它可以在数组中返回一个数组;也就是说,如果您编写的函数表现出非标准行为(将数组作为单个对象返回)。如果这是您的意图,那么您的解决方案会更好 - 然后就不需要 also 使用@()。是的,从技术上讲,这个答案并不完全符合 OP 的要求,但从总体上看,最好避免非标准行为;使用原始函数定义的另一个简单解决方案是使用 [array] $result1 = GetArrayWith1Hashtable
    • @mklement0 没有标准说明您必须从函数返回什么。并非所有函数都设计为在管道中使用。
    【解决方案2】:

    实际上,您只需在退回的商品前添加一个逗号,就像这样。这告诉 PowerShell 按原样返回它,而不是试图对它变得聪明。这还允许您在一个地方修复它,而不是在调用它的任何地方。

    function GetArrayWith1Hashtable()
    {
        $array = @()
    
        $hashtable = @{}
        $hashtable["a"] = "a" 
        $hashtable["b"] = "b" 
        $hashtable["c"] = "c"
        $array += $hashtable 
    
        Write-Host "GetArrayWith1Hashtable array.Length =" $array.Length
        Write-Host "GetArrayWith1Hashtable array.Count" $array.Count
        Write-Host "GetArrayWith1Hashtable array[0].Keys" $array[0].Keys
    
        # The only edit was to add the comma below
        ,$array
    }
    

    更新:虽然我不认为你想要这个功能,但我还是会提到它,以便其他人了解差异并为他们的方法做出明智的选择。

    为了让您的函数兼容以便在管道中更有效地使用,更好的方法是为每个项目调用 Write-Object。

    function GetArrayWith1Hashtable()
    {
        Write-Object "a" 
        Write-Object "b" 
        Write-Object "c"
    }
    

    通过使用 Write-Object,您允许 PowerShell 分别为每个对象调用管道中下一个命令的 Process block。否则它将调用下一个命令并将单个数组对象传递给它。你可以阅读更多关于piping objects here

    【讨论】:

    • 赞成这个答案,因为虽然接受的答案有效,但这个答案更干净地解决了问题,调用代码不需要任何修改。
    • 没错,@PhilChuang,调用者不需要修改,但另一方面,将数组作为单个对象发出的函数在管道中无法按预期工作。
    • @mklement0 正如我在对您的其他回复中所说的那样,您假设很多并且没有回答操作员的要求。并非所有函数都打算在管道中使用。
    • @JohnC:正如对另一个答案的评论中所述,您的回答为 as ask 问题提供了解决方案(这就是我赞成它的原因),但非常您刚刚提出的观点值得成为您答案的一部分:对于预计不会在管道中使用的简单辅助函数,可以使用这种方法。有了这些知识,读者就可以决定哪种方法适合他们。
    • “Write-Object”一词未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多