PowerShell相当于LINQ SelectMany方法

时间:2011-03-09 04:45:52

标签: linq powershell

我正在编写PowerShell代码来获取所有本地IPv4地址,不包括环回地址。我需要类似LINQ SelectMany方法的东西,但我无法弄清楚如何用PS滤镜做到这一点。这是我到目前为止的代码,它使用一个普通的旧ArrayList:

function Get-Computer-IP-Address()
{
    $ipAddresses = New-Object System.Collections.ArrayList

    $networkAdaptersWithIp = Get-WmiObject Win32_NetworkAdapterConfiguration | ? { $_.IPAddress -ne $null }
    foreach ($networkAdapter in $networkAdaptersWithIp)
    {
        foreach ($ipAddress in $networkAdapter.IPAddress)
        {
            if ($ipAddress -notlike "127.*" -and $ipAddress -notlike "*::*")
            {
                $ipAddresses.Add($ipAddress)
            }
        }
    }

    if ($ipAddresses.Length -eq 0)
    {
        throw "Failed to find any non-loopback IPv4 addresses"
    }

    return $ipAddresses
}

我想知道是否有更简洁的方法,只需更少的代码。

4 个答案:

答案 0 :(得分:21)

如果您将Foreach-ObjectWhere-Object组合在一起,就可以这样做:

$ipaddresses = @(
  Get-WmiObject Win32_NetworkAdapterConfiguration | 
  ? { $_.IPAddress -ne $null } |
  % { $_.IPAddress } |
  ? { $_ -notlike "127.*" -and $_ -notlike "*::*" })

请注意@(...)。这导致如果内部管道的结果是 nothing ,则将空数组分配给$ipaddresses

答案 1 :(得分:15)

只是回答这个问题 “PowerShell相当于LINQ SelectMany方法”

collection.SelectMany(el => el.GetChildren()) // SelectMany in C#

相当于

$collection | % { $_ }                    # SelectMany in PowerShell for array of arrays
$collection | % { $_.GetChildren() }      # SelectMany in PowerShell for complex object

实施例

$a = (1,2,3),('X','F'),'u','y'
$a.Length                # output is 4
($a | % { $_ }).Length   # output is 7

另一个例子

$dirs = dir -dir c:
$childFiles = $dirs | % { $_.GetFiles() }
$dirs.Length          # output is 6
$childFiles.Length    # output is 119

答案 2 :(得分:8)

我还要提到,SelectMany的PowerShell等价物是Select-Object -ExpandProperty <property name of a collection>。但是,对于此示例,这不能很好地工作,因为属性IPAddress是一个字符串数组。将字符串产品数组展平为具有附加其他属性的单个字符串,例如:

Get-WmiObject Win32_NetworkAdapterConfiguration | Where {$_.IPAddress} | 
    Select Description -Expand IPAddress

不幸的是,PowerShell专门处理System.String个对象,因此除了字符串的值(本例中为IPAddress)之外,它不希望显示任何内容。让它也显示其他属性(本例中的描述)是不实际的(可能吗?)AFAICT。

答案 3 :(得分:-1)

迟到总比没有好。 我来到了下一个方法(代码是PowerShell 2.0和PowerShell 3.0的混合):


    if(-not (test-path variable:psversiontable)){return}
    rv -ea silentlycontinue -force *
    cls
    $major=$psversiontable.psversion.major
    $linqenum=[linq.enumerable]
    'min:'+$linqenum::min([int[]](170..180))
    'max:'+$linqenum::max($linqenum::range(170,170))
    $membertypes=[reflection.membertypes]
    $bindflags=[reflection.bindingflags]
    [reflection.membertypes]$type=$membertypes::method
    [reflection.bindingflags]$attr=$bindflags::public,$bindflags::static
    $name='Min'
    $methods=$linqenum.getmember($name,$type,$attr)|?{$_.isgenericmethod}
    $method=$methods[0]
    $closed=$method.makegenericmethod((,[int]))
    "$name`:"+$closed.Invoke($null,(,[int[]](170..180)))
    $name='Max'
    $methods=$linqenum.getmember($name,$type,$attr)|?{$_.isgenericmethod}
    $method=$methods[0]
    $closed=$method.makegenericmethod((,[int]))
    "$name`:"+$closed.Invoke($null,(,$linqenum::range(170,170)))
    $name='SelectMany'
    $methods=$linqenum.getmember($name,$type,$attr)|?{$_.isgenericmethod}
    $method=$methods[0]
    #$params=[hashtable],[string]
    #$closed=$method.makegenericmethod($params)
    $closed=$method.makegenericmethod(([hashtable],[string]))
    [hashtable[]]$owners=@{name="Sidney";pets=("Scruffy","Sam")},
                         @{name="Ronen";pets=("Walker","Sugar")},
                         @{name="Hines";pets=(,"Dusty")},
                         @{name="Vernette";pets=("Scratches","Diesel")}
    if($major -eq 2){
     $delegate=[func[hashtable,collections.generic.ienumerable[string]]]
     $sb={param([hashtable]$owner) ,[string[]]$owner.pets}
    }else{
     $delegate=[func[hashtable,string[]]]
     $sb={param($owner) $owner.pets}
    }
    $selector=$sb -as $delegate
    $params=$owners,$selector
    $pets=$closed.Invoke($null,$params)
    "`n$name`n$('-'*$name.length)"
    $pets
    $method=$methods[3]
    $params=[hashtable],[string],[hashtable]
    $closed=$method.makegenericmethod($params)
    $resultsb={param($owner,$pet)@{owner=$owner.name;pet=$pet}}
    #$resultdelegate=[func[hashtable,string,hashtable]]
    #$result=$resultsb -as $resultdelegate
    $params=$owners,$selector,[func[hashtable,string,hashtable]]$resultsb
    $ownerpet=$closed.Invoke($null,$params)
    $ownerpet|select values|ft -auto
    if($major -gt 2){
     $linqenum::selectmany(
      $owners,
      [func[hashtable,string[]]]`
      {param($owner) $owner.pets},
      [func[hashtable,string,hashtable]]`
      {param($owner,$pet)@{owner=$owner.name;pet=$pet}}
     )|select values|ft -auto
     $linqenum::selectmany(
      [int[]](1..4),
      [func[int,int[]]]`
      {param($left) 11..(11+$left-1)},
      [func[int,int,hashtable]]`
      {param($left,$right)@{left=$left;right=$right}}
     )|select values|ft -auto
     $linqenum::selectmany(
      $linqenum::range(1,4),
      [func[int,int[]]]`
      {param($left) $linqenum::range(11,$left)},
      [func[int,int,hashtable]]`
      {param($left,$right)@{left=$left;right=$right}}
     )|select values|ft -auto
     $name='Join'
     [hashtable[]]$person=@{id=1;name='ivan'},@{id=2;name='vasilij'},@{id=3;name='pjotr'}
     [hashtable[]]$job=@{id=1;job='tokar'},@{id=1;job='pekar'},
                       @{id=2;job='doctor'},
                       @{id=3;job='soldat'},@{id=3;job='milicioner'},@{id=3;job='jurist'}
     "`n$name`n$('-'*$name.length)"
     [linq.enumerable]::join(
      $person,$job,
      [func[hashtable,int]]{param($p) $p.id},
      [func[hashtable,int]]{param($p) $p.id},
      [func[hashtable,hashtable,hashtable]]`
      {param($p,$j) @{name=$p.name;job=$j.job}}
     )|select values|ft -auto
    }