1

I'm writing a PowerShell script that needs to check if items in array $arrayEmail are in array $empListEmail and throw those values in another array C. Array A has 9,500+ items and array B doesn't have many. Surprisingly, I have not seen an example that performs this. I've been searching Google for two days. Here is what I have now, but the comparison doesn't work at all like it should.

function MatchUsers {
$array = Get-Content -Raw -Path PassDataOut.json | ConvertFrom-Json

Import-Module ActiveDirectory  # Load the Active Directory module

Set-Location AD: # Change into Active Directory

set-location "DC=graytv,DC=corp"  # Sets the location to the Gray TV Corporate directory


$empList = Get-ADUser -filter 'Enabled -eq "False"' -searchbase "OU=domain Users,DC=graytv,DC=corp"
$arrayTemp = $array.Email
$arrayEmail = $arrayTemp.trim()
$empListEmail = $empList.UserPrincipalName

$NotInList = @($arrayEmail) -notin $empListEmail
Write-Host $NotInList

3 Answers3

1

One option you would likely get for this when googling may have been Compare-Object, but using the -notin operator works as well. The issue comes from attempting to compare the entirety of the list to another list. You have to iterate through the contents to check against the list:

$arrayEmail.Where{$_ -notin $empListEmail}
Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24
1

Turn the second list into a HashSet<string> - it'll be much faster to search than an array:

$empListEmail = [System.Collections.Generic.HashSet[string]]::new([string[]]$empList.UserPrincipalName, [StringComparer]::OrdinalIgnoreCase)

$NotInList = $arrayEmail |Where-Object { -not $empListEmail.Contains($_) }
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
1

If you don't mind having unique emails in $arrayEmail this is a similar take on Mathias's answer but reversing the order for the HashSet<T> and using it's .ExceptWith Method for filtering.

$arrayEmail = [System.Collections.Generic.HashSet[string]]::new(
    [string[]] $array.Email.Trim(),
    [StringComparer]::OrdinalIgnoreCase
)

$arrayEmail.ExceptWith([string[]] $empList.UserPrincipalName)
$arrayEmail # => updated to only values not in `$empList.UserPrincipalName`

Based on feedback from comments, seems like you were looking for the opposite in this case, find all those elements in $array.Email which are also present in $empList.UserPrincipalName. In that case, you only need to change the method to .IntersectWith:

$arrayEmail = [System.Collections.Generic.HashSet[string]]::new(
    [string[]] $array.Email.Trim(),
    [StringComparer]::OrdinalIgnoreCase
)

$arrayEmail.IntersectWith([string[]] $empList.UserPrincipalName)
$arrayEmail # => updated to only values present in `$empList.UserPrincipalName`
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • The $arrayEmail is the one having the 9500+ users. The $empListEmail will be the smaller one. Is this for that scenario? – Timothy Waters Nov 09 '22 at 18:11
  • 1
    @TimothyWaters are you asking if this will perform well enough? If so, yes, it will perform well – Santiago Squarzon Nov 09 '22 at 18:26
  • How do I update this to values in common to both arrays? – Timothy Waters Nov 09 '22 at 18:53
  • This doesn't work for that use case nor the other answers posted here, this is comparing 1 collection against the other and what you seem to be looking for is comparing the 2 collections against each other – Santiago Squarzon Nov 09 '22 at 18:55
  • My apologies, I'm terrible at explaining things. – Timothy Waters Nov 09 '22 at 18:56
  • Ok, the big array is a giant list of 9500 email addresses for our 1Password users. The other array is a list of Employee email address for employees whose enable status is False. I need to take an email from the 1Password array and see if it is in the Enable=False email address array. If the 1Password email address is also in the Enabled=False email array, I need to put that email address into a third array for deletion later. – Timothy Waters Nov 09 '22 at 19:00
  • 1
    @TimothyWaters ok so, you want the opposite of what you have asked in your question :P you want to find `$array.Email` that __are present in__ `$empList.UserPrincipalName` – Santiago Squarzon Nov 09 '22 at 19:04
  • 1
    @TimothyWaters if what I stated in my previous comment is actually what you're looking for, then you only need to change `.ExceptWith` for `.IntersectWith` – Santiago Squarzon Nov 09 '22 at 19:10
  • @TimothyWaters, for the opposite: `$InList = $empListEmail.where{ $arrayEmail -eq $_ }` see also: [Fastest Way to get a uniquely index item from the property of an array](https://stackoverflow.com/a/59437162/1701026) (both referred answers have performance measurements). But reading the comments, I get the feeling you not dealing with ***scalar* arrays** but ***object* arrays** (also knowing that an array of 9500 scalar entries isn't that big). For joining object arrays, see: [In PowerShell, what's the best way to join two tables into one?](https://stackoverflow.com/a/45483110/1701026) – iRon Nov 10 '22 at 06:41
  • 1
    Thank you, @SantiagoSquarzon, for you help! I've learned a lot! – Timothy Waters Nov 10 '22 at 14:45
  • 1
    Thank you, @iRon , for you help! I've learned a lot! – Timothy Waters Nov 10 '22 at 14:45