【问题标题】:What's the quickest way to find matches in two arrays containing objects in Powershell?在 Powershell 中包含对象的两个数组中查找匹配项的最快方法是什么?
【发布时间】:2012-07-16 16:29:14
【问题描述】:

我在两个数组中有许多对象。每个对象都有相同的属性。

示例对象:

$obj1 = New-Object System.Object;
$obj1 | Add-Member -Type NoteProperty -Name FirstName 'George'; 
$obj1 | Add-Member -Type NoteProperty -Name LastName 'Banks';
$obj1 | Add-Member -Type NoteProperty -Name EmployeeID '1903'; 

数组:

$array1 = @($obj1,$obj2,$obj3);
$array2 = @($obj5,$obj3,$obj9);

我的目标是基于两个因素以 1:1 的关系匹配每个数组中的每个对象;匹配 EmployeeID,或者如果未填充 EmployeeID,则匹配 FirstName,LastName 组合。

例如,假设我有以下条件:

$obj1 = New-Object System.Object;
$obj1 | Add-Member -Type NoteProperty -Name FirstName 'George'; 
$obj1 | Add-Member -Type NoteProperty -Name LastName 'Banks';
$obj1 | Add-Member -Type NoteProperty -Name EmployeeID '1903'; 

$obj2 = New-Object System.Object;
$obj2 | Add-Member -Type NoteProperty -Name FirstName 'Paul'; 
$obj2 | Add-Member -Type NoteProperty -Name LastName 'Newman';
$obj2 | Add-Member -Type NoteProperty -Name EmployeeID '567';

$obj3 = New-Object System.Object;
$obj3 | Add-Member -Type NoteProperty -Name FirstName 'George'; 
$obj3 | Add-Member -Type NoteProperty -Name LastName 'Banks';
$obj3 | Add-Member -Type NoteProperty -Name EmployeeID '1903'; 

$obj4 = New-Object System.Object;
$obj4 | Add-Member -Type NoteProperty -Name FirstName 'Paul'; 
$obj4 | Add-Member -Type NoteProperty -Name LastName 'Newman';
$obj4 | Add-Member -Type NoteProperty -Name EmployeeID '';

$array1 = @($obj1,$obj2);
$array2 = @($obj3,$obj4);

在此示例中,我可以匹配 George Banks 的 EmployeeID,因为它存在于两个数组中。但是,Paul Newman 没有在 $array2 中填充 EmployeeID,所以我需要根据他的 FirstName/LastName 组合来匹配他。

最终,我想得到一个这样的数组输出,它将每个对象的所有属性合并到一个对象中。

$obj1.FirstName = 'George'
$obj1.LastName = 'Banks'
$obj1.EmployeeID = '1903'
$obj2.FirstName = 'Paul';
$obj2.LastName = 'Newman';
$obj2.EmployeeID = '567'

$aOutput = @($obj1,$obj2);

我这样做的真实原因有两个。

  1. 我有一个包含 FirstName、LastName、EmployeeID、Department 的员工电子表格。在 Active Directory 中,通常只填充 FirstName 和 LastName。我想获取电子表格中的数据并使用丢失的数据填充该用户的 Active Directory 用户帐户。

  2. 我们有数以千计的 Active Directory 用户帐户,这些帐户并未专门分配给实际员工,目前无法得知。我需要这个脚本来找到一种将实际员工与其各自的 Active Directory 用户帐户相匹配的方法,以便我们可以标记它。标记后,如果该用户帐户在 60 天内未通过身份验证,则该用户帐户将不会被删除。

【问题讨论】:

  • 我认为示例中 $obj3 的设置中存在复制粘贴错误。这一行:$obj2 | Add-Member -Type NoteProperty -Name EmployeeID '1903'; 应该引用 $obj3 而不是 $obj2。我会编辑它,但界面需要更改为至少 6 个字符。
  • 您可能想要调整您的示例,因为您想要的输出与您的输入相同,即 obj1 和 obj2 不会改变。虽然这基于输入是有效的,但它并不能说明更改会是什么样子。

标签: arrays object powershell active-directory


【解决方案1】:

我认为你想做这样的事情。此代码检查员工 ID 是否匹配,或者名字和姓氏的串联是否匹配。如果是这样,它将检查数组 1 中对象中的每个字段以查看它是否为空。如果是,则复制数组 2 中匹配对象中对应字段的内容。

foreach ($employee1 in $array1) { 
    foreach ($employee2 in $array2) {
        if( ($employee1.EmployeeID -eq $employee2.EmployeeID) -or 
            ("$($employee1.FirstName)$($employee1.LastName)" -eq "$($employee2.FirstName)$($employee2.LastName)")) {
            if ([string]::IsNullOrEmpty($employee1.FirstName)) {
                $employee1.FirstName = $employee2.FirstName
            } elseif ([string]::IsNullOrEmpty($employee1.LastName)) {
                $employee1.LastName = $employee2.LastName
            } elseif ([string]::IsNullOrEmpty($employee1.EmployeeID)) {
                $employee1.EmployeeID = $employee2.EmployeeID
            }       
        } 
    } 
}

需要考虑的几点:

  1. 您可能想要创建一组新对象,对更改进行完整性检查,然后复制原始对象。
  2. 如果您有不同人的名字和姓氏相同的条目,则此代码将失效。
  3. 此代码不考虑对应字段均为空的情况。

【讨论】:

    【解决方案2】:

    历经千辛万苦,我终于得到了它。我最终做的是将所有对象属性转换为正则表达式字符串,然后基于该字符串进行匹配。

    【讨论】:

      猜你喜欢
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      相关资源
      最近更新 更多