Powershell fastest way to merge two arrays using a common property?

Viewed 221

What's the fastest way to merge two arrays using a common property?

Users | Select *
Username : Joe.Doe
Office   : Chicago
Email    :

Username : Mike.Smith
Office   : New York
Email    :
...
UserEmails | Select *
AccountEmail  : Mike.Smith
EmailAddress  : mike-smith@example.com

AccountEmail  : Joe.Doe
EmailAddress  : jsmith12@example.com
...

The merge should result in:

UsersCompleteList | Select *
Username : Joe.Doe
Office   : Chicago
Email    : jsmith12@example.com

Username : Mike.Smith
Office   : New York
Email    : mike-smith@example.com
...

Something like for each ($user in $users) { ($user.Email = $userEmails | ? { $_.AccountEmail -eq $user.Username}).EmailAddress takes ages on large datasets.

1 Answers

Loop through one collection and store the values in a hash. Then loop through the other collection and pull the value back out of the hash. Something like:

$hash = @{}
$userEmails | %{ $hash[$_.AccountEmail] = $_.EmailAddress }
$users | %{ $_.Email = $hash[$_.Username] }

If you have other properties you can just store the original object:

$hash = @{}
$userEmails | %{ $hash[$_.AccountEmail] = $_ }
$users | %{ 
   $item = $hash[$_.Username]
   $_.Email = $item.EmailAddress
   $_.Other = $item.SomethingElse
}

Or with loops instead of ForEach-Object including:

$hash = @{}
foreach($e in $userEmails) {
  $hash[$e.AccountEmail] = $e
}
foreach($u in $users) {
  $item = $hash[$u.UserName]
  if ($item -ne $null) {
    $u.Email = $item.EmailAddress
  }
} 
Related