Need guidance on creating a new object that stores user information after comparing it

I have some code that I will show below; that compares 2 objects using LINQ. There are 2 variables I have. 1 is the comparison of new items that need to be added, and the other is of items that need to be deleted.

When I do the comparison it works fine, but it compares firstnames first, then middle initial, then lastname and so forth. When I print out the variable at the very end it print it out in the same order. first names first then middle initial then last names…

What I am trying to do instead is organize it in a table that outputs it in order so for example it outputs the user and all of it’s attributes.

Here is my code.

#Our Array of values we will be comparing
[array]$CompareValues = "FirstName","MiddleName","LastName","DisplayName","Email","Mobile","TelephoneNumber","Title","Dept","Company"

for($i=0; $i -lt $CompareValues.Count; $i++)
    #First let's create 2 variables that will hold the info we want
    $A = ($Users).($CompareValues[$i])
    $B = ($Contacts).($CompareValues[$i])

    ##################### Compare existing contacts to Users #####################

    #Only Run if there are contacts; otherwise there is nothing for us to compare
    if(($NULL -ne $B))
        #Displays what accounts we need to import
        $NeedsToBeAdded += [string[]]([Linq.Enumerable]::Except([object[]]$a, [object[]]$b))

        #Displays what accounts we need to delete because they no longer exist
        $NeedsToBeDeleted += [string[]]([Linq.Enumerable]::Except([object[]]$b, [object[]]$a))

Here is how it prints (as an example)








And here is how I would like it to print as an example (no delimiter necessary I’m just using the comma for readability)

Bob , , Jones, Bjones,, 123-456-7890, , Manager, HR, CompanyName
Mary , , joe, Mjoe,, 123-456-7891, , Accountant, Accounting, CompanyName
John , , Nowak, Jnowak,, 123-456-7892, , Engineer, IT, CompanyName

How can I achieve something like this? My end goal is after I get it all stored in the variable correctly, I will go through each object and then update the contact list either add the new users with the attributes above, or delete the user and their contact info because they no longer exist.


First of all, you’re only updating a contact if that specific value is not in the list already, which will cause problems. For example, let’s look at last names:

$Users.LastName $Contacts.LastName
--------------- ------------------
Smith           Joe     # 
Joe-Jones       Joe     #
Smith           Nowak   ## These three changed
Smith           Smith
Joe             Joe
Nowak           Nowak

If you were to compare these by name, your script would only return one new entry. Here, two users have changed their last name to smith:

$A = ($Users).LastName
$B = ($Contacts).LastName

$NeedsToBeAdded += [string[]]([Linq.Enumerable]::Except([object[]]$a, [object[]]$b))

Joe-Jones  # Missing two changes!

“Smith” was already in the contacts list, so no difference is seen.

Instead, you’ll need to compare each entire object, or have some kind of unique ID to match users and contacts on. The simplest answer for what you have is Compare-Object where you add all the properties you want to compare on:

$Diff = Compare-Object $Users $Contacts -Property FirstName,LastName,Email -PassThru

$NeedsToBeAdded   = $diff | Where SideIndicator -eq '=>'
$NeedsToBeDeleted = $diff | Where SideIndicator -eq '<='

-PassThru lets it output the a original object:

$NeedsToBeAdded | ft FirstName,LastName,Email

FirstName LastName  Email            
--------- --------  -----            
Bob       Smith
Mary      Joe-Jones  
John      Smith