【问题标题】:What is the Linq.First equivalent in PowerShell?PowerShell 中的 Linq.First 等价物是什么?
【发布时间】:2011-07-18 14:59:07
【问题描述】:

下面的 sn-p 从文件列表中检测哪些是 Ftp 上的目录

作为 C# 它将如下所示

var files = new List<string>(){"App_Data", "bin", "Content"};
var line = "drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data"
var dir = files.First(x => line.EndsWith(x));

如何翻译 PowerShell 中的最后一行?

【问题讨论】:

    标签: c# linq powershell lambda


    【解决方案1】:

    这样的……

    $files = @("App_Data", "bin", "Content")
    $line = "drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data"
    $dir = $files | Where { $line.EndsWith($_) } | Select -First 1
    

    最后一行的这些版本都将完成相同的操作:

    $dir = @($files | Where { $line.EndsWith($_) })[0]
    
    $dir = $files | Where { $line.EndsWith($_) } | Select -index 0
    
    $dir = $files | Where { $line.EndsWith($_) } | Select -First 1
    

    有人指出,上面的行为与 Linq.First 并不完全等价,因为 Linq.First 在两种情况下会抛出异常:

    • 当源或谓词为空时引发 ArgumentNullException。
    • 当源序列为空或没有元素满足谓词条件时抛出 InvalidOperationException。

    如果您确实想要这种行为,则需要一些额外的保护代码。

    【讨论】:

    • 编辑修复,因为我发布的第一个版本没有实现 First() 的等效功能。
    • 最后一个示例可能是最“规范”的,除了指定 Select 别名而不是 Select-Object 更为常规 - 就像您为 Where-Object 所做的那样。
    • 对于任何想知道的人,where {...} | Select -First 会“短路”。也就是说,如果您在上面的示例中搜索一百万个文件,并且在 10 个文件之后找到匹配项,那么结果会立即返回。 PowerShell 不会搜索剩余的文件。
    • 我的假设是否正确,上面的示例都是 FirstOrDefault 的等价物,但不是 First 方法的等价物?如果在集合中找不到匹配项,第一个方法应该引发异常。
    • @pholpar 感谢您指出这一点,我用该信息更新了答案。
    【解决方案2】:

    正如 Robert Groves 所说,Select-Object -First Occurence 可以解决问题,您也可以使用 -Last Occurence。

    顺便说一句,与任何其他静态 .Net 方法一样,您可以在 powershell 中使用 linq。

    [Linq.Enumerable]::First($list)
    
    [Linq.Enumerable]::Distinct($list)
    
    [Linq.Enumerable]::Where($list, [Func[int,bool]]{ param($item) $item -gt 1 })
    

    【讨论】:

      【解决方案3】:

      Doug Finke 制作了一个关于将 C# 转换为 Powershell 的精彩视频(仅 7 分钟) http://dougfinke.com/video/CSharpToPowerShell.html

      Roberts 的例子确实很好,虽然逗号分隔会被隐式地当作一个数组来处理

      这样做的最短方法是将它们全部放入一个管道中:

      $dir = "App_Data", "bin", "Content" | % { if("drwxr-xr-x 1 ftp ftp              0 Mar 18 22:41 App_Data".EndsWith($_)) { $_ } } | select -first 1
      

      【讨论】:

      • 感谢詹姆斯链接到我的视频
      • 这不起作用。您的 Foreach 阶段正在输出 EndsWith() 调用的结果,这是一个布尔值。
      • 感谢 Keith :) 应该是 $dir = "App_Data", "bin", "Content" | % { if ("drwxr-xr-x 1 ftp ftp 0 Mar 18 22:41 App_Data".EndsWith($_)){ $_ } } | select -first 1
      【解决方案4】:

      这是First 的一个非常简单的实现:

      function First($collection)
      {
          foreach ($item in $collection)
          {
              return $item
          }
          return $null
      }
      

      您可以抛出InvalidOperationException 异常,而不是返回$null

      【讨论】:

      • 这不会从管道中获取输入,例如你不能这样做1..10 | First
      猜你喜欢
      • 2016-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      相关资源
      最近更新 更多