代码之家  ›  专栏  ›  技术社区  ›  Tom H zenazn

在Powershell中的对象数组中查找匹配项

  •  3
  • Tom H zenazn  · 技术社区  · 14 年前

    $filteredSQLObjects = @()
    
    foreach ($SQLObject1 in $SQLObjects1)
    {
        foreach ($SQLObject2 in $SQLObjects2)
        {
            if ($SQLObject1.Name   -eq $SQLObject2.Name -and
                $SQLObject1.Schema -eq $SQLObject2.Schema)
            {
                $filteredSQLObjects += $SQLObject1
            }
        }
    }
    

    谢谢!

    2 回复  |  直到 14 年前
        1
  •  4
  •   George Howarth    14 年前

    我认为在一个例子中定义相等条件更好 IsEqualTo 方法。比如说:

    $myObject = New-Object PSObject
    $myObject | Add-Member -MemberType NoteProperty -Name Name -Value $name
    $myObject | Add-Member -MemberType NoteProperty -Name Schema -Value $schema
    $myObject | Add-Member -MemberType ScriptMethod -Name IsEqualTo -Value {
        param (
            [PSObject]$Object
        )
    
        return (($this.Name -eq $Object.Name) -and ($this.Schema -eq $Object.Schema))
    }
    

    然后你要么像基思给我们看的那样做一行,要么就做两行 foreach 迭代。无论你认为哪个更易读:

    $filteredSQLObjects = $SQLObjects1 | Where-Object { $SQLObject1 = $_; $SQLObjects2 | Where-Object { $_.IsEqualTo($SQLOBject1) } }
    

    foreach ($SQLObject1 in $SQLObjects1)
    {
        foreach ($SQLObject2 in $SQLObjects2)
        {
            if ($SQLObject1.IsEqualTo($SQLObject2))
            {
                $filteredSQLObjects += $SQLObject1
            }
        }
    }
    

    编辑

    好吧,首先,你不能添加 Equals 成员,因为它已存在于 System.Object (嘘!)。所以我想 等质量

    您可以定义自己的函数 Intersect-Object (相当于.NET的 Enumerable.Intersect Sequence 有一个 等质量 方法,在添加到之前不检查重复项 $filteredSequence

    function Intersect-Object
    {
        param (
            [Parameter(ValueFromPipeline = $true)]
            [PSObject]$Object,
            [Parameter(Mandatory = $true)]
            [PSObject[]]$Sequence
        )
    
        begin
        {
            $filteredSequence = @()
        }
    
        process
        {
            $Sequence | Where-Object { $_.IsEqualTo($Object) } | ForEach-Object { $filteredSequence += $_ }
        }
    
        end
        {
            return $filteredSequence
        }
    }
    

    然后你的替身 foreach公司

    $filteredSQLObjects = $SQLObjects1 | Intersect-Object -Sequence $SQLObjects2
    
        2
  •  2
  •   Keith Hill    14 年前

    你可以把它浓缩成一行,如果你在控制台写的话,这是合适的:

    $filtered = $SQLObjects1 | ? {$o1=$_; $SQLObjects2 | ? {$_.Name -eq $o1.Schema `
                                                       -and $_.Name -eq $o1.Schema}}
    

    但在脚本中,我会像你一样展开它。这样可读性更强。