代码之家  ›  专栏  ›  技术社区  ›  Kangles

谓词脚本块和集合?

  •  2
  • Kangles  · 技术社区  · 7 月前
    Function Invoke-Keep {
        <#
        .SYNOPSIS
        Implement the keep operation on collections, including nested arrays.
        
        .DESCRIPTION
        Given a collection (which may contain nested arrays), apply the predicate to each element and return an array of elements where the predicate is true.
    
        .PARAMETER Data
        Collection of data to filter through, can be nested arrays.
    
        .PARAMETER Predicate
        The predicate to operate on the data.
    
        .EXAMPLE
        $IsSumGreaterThan10 = { param($row) ($row | Measure-Object -Sum).Sum -gt 10 }
        Invoke-Keep -Data @(@(1, 2, 3), @(5, 6), @(10, 5), @(7, 3)) -Predicate $IsSumGreaterThan10
        Return: @(@(5, 6), @(10, 5), @(7, 3))
        #>
    

    在尝试创建上述函数(并使用.EXAMPLE.中的谓词和数据对其进行测试)时,我发现案例1失败,案例2成功,但不清楚原因:

    案例1:

    [CmdletBinding()]
        Param(
            [Object[]]$Data,
            [ScriptBlock]$Predicate
        )
        foreach ($item in $Data) {
            if ($Predicate.Invoke($Item)) {
                return $item
            }
        }
    
    

    案例2:

    [CmdletBinding()]
        Param(
            [Object[]]$Data,
            [ScriptBlock]$Predicate
        )
       return $Data | Where-Object {& $Predicate $_}
    }
    

    案例1似乎可以很好地处理平面数据,但在传递嵌套数组时什么也不返回。案例2很好地处理了嵌套数组。但是whwhwhwhWhwhwhwh?!

    这可能已经得到了答案,但我足够愚蠢,甚至没有语言在搜索框中表达我的问题。

    1 回复  |  直到 7 月前
        1
  •  1
  •   mklement0    7 月前

    案例1:

    替换:

            if ($Predicate.Invoke($Item)) {
                return $item
            }
    

    与:

            if (& $Predicate $item) {
              , $item
            }
    
    • 你的主要问题是 .Invoke() 方法需要一个 阵列 参数,如果你想传递一个数组作为 单一的 参数,您必须将该参数包装在单个元素辅助数组中。

      • 然而,使用 & ,the call operator ,使用参数调用脚本块会使这变得不必要,并且使用 & 在PowerShell代码中通常更可取。
    • 第二个问题是使用 return 在你的 foreach 块,在找到后将停止处理 比赛。

      • 遗漏 返回 原则上解决了这个问题,但请注意,如果 $item 就其本身而言,他们取得了成功 output stream ,这将取决于 自动枚举 并将输出每个匹配嵌套数组的元素 逐一地 .

      • 使用一元形式 , 这个 array-constructor ("comma") operator 实际上阻止了这一点。

        • 一个概念上更清晰但速度较慢的替代方案是使用
          Write-Output -NoEnumerate $item .
        • 请参阅 this answer 了解背景信息。

    案例2奏效的原因是使用 $Data 数组作为管道输入会导致其 枚举 ,以便传递元素(在您的情况下是嵌套数组) 逐一地 Where-Object ,因此 automatic $_ variable 在脚本块中正确引用每个嵌套数组。

    推荐文章