【问题标题】:What is the PowerShell equivalent of LINQ's All()?LINQ 的 All() 的 PowerShell 等价物是什么?
【发布时间】:2016-02-07 19:42:23
【问题描述】:

我正在尝试测试某个条件是否适用于 PowerShell 中数组中的所有项目(类似于 LINQ 的 All 函数)。除了编写手动 for 循环之外,在 PowerShell 中执行此操作的“正确”方法是什么?

具体来说,here 是我试图从 C# 翻译的代码:

public static IEnumerable<string> FilterNamespaces(IEnumerable<string> namespaces)
  => namespaces
     .Where(ns => namespaces
       .Where(n => n != ns)
         .All(n => !Regex.IsMatch(n, $@"{Regex.Escape(ns)}[\.\n]")))
     .Distinct();

【问题讨论】:

  • @Matt Hm,有趣的想法。那么是这样的:$filtered = $array -Match $pred; if ($filtered.Length -eq $array.Length)?
  • 看不到这些变量是什么......理论上是的。
  • 您能否发布一个您正在测试真/假条件的项目的示例?
  • 虽然这个问题有点偶然,但它有助于理解这段代码的作用:从命名空间列表中,它只返回共享路径中具有 最长 路径的那些父路径;例如,如果 System.WindowsSystem.Windows.Input 都存在,则仅返回 System.Windows.Input。我对正则表达式中的 \n 感到困惑,但是 - 最后不是 \. 吗?

标签: linq powershell


【解决方案1】:

我不会在 powershell 中重新创建 C# 代码,而是以 PowerShell 方式进行。例如:

function Filter-Namespaces ([string[]]$Namespaces) {
  $Namespaces | Where-Object {
    $thisNamespace = $_;
    (
      $Namespaces | ForEach-Object { $_ -match "^$([regex]::Escape($thisNamespace))\." }
    ) -notcontains $true
  } | Select-Object -Unique
}

Filter-Namespaces -Namespaces $values

System.Windows.Input
System.Windows.Converters
System.Windows.Markup.Primitives
System.IO.Packaging

但是,要回答您的问题,您可以手动进行:

$values = "System",
"System.Windows",
"System.Windows.Input",
"System.Windows.Converters",
"System.Windows.Markup",
"System.Windows.Markup.Primitives",
"System.IO",
"System.IO.Packaging"

($values | ForEach-Object { $_ -match 'System' }) -notcontains $false

True

或者你可以为它创建一个函数:

function Test-All {
    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$true)]
    $Condition,
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
    $InputObject
    )

    begin { $result = $true }
    process {
        $InputObject | Foreach-Object { 
            if (-not (& $Condition)) { $result = $false }
        }
    }
    end { $result }
}

$values = "System",
"System.Windows",
"System.Windows.Input",
"System.Windows.Converters",
"System.Windows.Markup",
"System.Windows.Markup.Primitives",
"System.IO",
"System.IO.Packaging"

#Using pipeline
$values | Test-All { $_ -match 'System' }

#Using array arguemtn
Test-All -Condition { $_ -match 'System' } -InputObject $values
#Using single value argument
Test-All -Condition { $_ -match 'System' } -InputObject $values[0]

或者您可以编译 C# 代码或使用 Add-Type 加载已编译的 dll。

【讨论】:

  • 这是我所想的更复杂的版本。对我来说似乎是缓慢的一天。
  • @Matt,我可能从我的个人模块中复制了该功能。 “手动方式”是实时的。 :)
  • $InputObject 应该从 &amp; $Condition $InputObject 中删除,因为这给人的印象是它是作为参数传递给脚本块的。这只有在脚本块本身中定义了一个参数时才有效,例如{ param($Arg) $Arg -match 'System' }。该示例仍然有效的原因是自动变量$_ 恰好与进程块中的$InputObject 保持相同的值。
  • @lujomu,哇,这是一个旧的。 :-) 可能有一些想法在重写中丢失了 - 不记得了,但我已经更新了 PoC 以支持管道和参数输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-25
  • 2011-07-18
  • 2010-11-16
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多