Find elements that are in array1 but NOT in array2

I pulled two lists of computers from two different tools: Array1

and Array2

.

Now I need to extract the ones that are in Array1

, but not in Array2

.

I managed to get all that fit by following these steps:

$matchingComp = @()

foreach ($SCCMcomputer in $SCCMcomputers) {
    foreach ($eWPTcomputer in $eWPTcomputers) {
        if ($SCCMcomputer.Computername -eq $eWPTComputer.Computername) {
            $obj = New-Object PSObject
            $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $SCCMcomputer.Computername
            $matchingComp +=$obj
        }
    }
}

$matchingComp | Export-Csv $inEWPT -Delimiter "," -NoTypeInformation

      

But I still need the ones that are in $SCCMcomputer

, but NOT in $eWPTcomputers

...

I found some solutions on SO with other languages ​​(like Perl) but not for PowerShell.

UPDATE

I still am not getting the correct output in Excel with this formula:

enter image description here

the output looks like this:

enter image description here

means some are here and some are not. The result in powershell looks like this:

enter image description here

means 0KB is emtpy.

$SCCMcomputers | Export-Csv $sccmexport -Delimiter "," -NoTypeInformation
$eWPTcomputers | Export-Csv $ewptexport -Delimiter "," -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=>"} |select inputobject | Export-Csv $inEWPT -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=="} |select inputobject | Export-Csv $inBoth -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "<="} |select inputobject | Export-Csv $inSCCM -NoTypeInformation

      

And both column names (or whatever it was called) from SCCMcomptuers / eWPTcomputers are "Computername"

Any idea what I might be doing wrong? Both computer arrays are generated from SQL and in hashtables (I think it is called):, @{Computername=......}@{Computername....

something like this.

Update 2

foreach ($t in $sccmComputers) {
    $Test1 += $t.computername
}

$Test2 = @()
foreach ($t in $ewptComputers) {
    $Test2 += $t.computername
}

      

Removing the Hashtable header and just having arrays filled with strings works in fantasy ... does -Property computername

n't even work ...: S

+3


source to share


5 answers


use compare-object

cmdlet

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt | ?{$_.sideIndicator -eq "<="} |select inputobject

example:

$sccm=@(1,2,3)   
$wpt=@(2,4)

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -IncludeEqual   

      



will output:

InputObject SideIndicator


      2 ==            
      4 =>            
      1 <=            
      3 <=

      

which means that the value "2" is on both objects "1" and "3" only on the "left side" (that is, on the control object), and "4" is only on the difference object

+9


source


Use compare-object

like this

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -passthru

      

This should only give you objects in $ sccm, not in $ wpt.

CORRECTION:

The above code will work for the case where the DifferenceObject is guaranteed to be a subset of the ReferenceObject. However, it will FAIL if there are additional objects in the DifferenceObject that are also not present in the ReferenceObject. The above code returns any objects that are present in the EOTER ReferenceObject OR DifferenceObject, but NOT in both.



To correctly return ONLY objects in a ReferenceObject that are also not present in a DifferenceObject, the following code is required:

Compare-Object -ReferenceObject $sccm  -DifferenceObject $wpt | 
    Where-Object { $_.SideIndicator -eq '<=' } | 
    ForEach-Object  { Write-Output $_.InputObject }

      

The clause where-object

ensures that only objects that are present in the ReferenceObject are piped.

The sentence foreach-object

returns the result back to a plain array (ref: Convert Custom Object Arrays to String Arrays in Powershell - thanks Keith)

+2


source


Compare-Object method is really the best. What hasn't been covered yet is the clean output to your Excel file.

Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Export-Csv sccm-only.csv -NoTypeInformation

      

will create two columns. One with "InputObject" and the names of your computer, and another column with "SideIndicator" and a bunch of strings with "<=".

An easy fix is ​​to select only the column you want:

Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object InputObject | Export-Csv sccm-only.csv -NoTypeInformation

      

This will give you one column labeled "InputObject" and the names of your computer.

If you want to change the column label, use a method from another thread, Windows Powershell Rename the column header CSV file :

Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

      

Also, just change the SideIndicator comparison to get these computers on both systems, or only in eWPT:

# Only in eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '=>' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

# In both SCCM and eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '==' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

      

+1


source


You can use -contains

and-notcontains

$A1 ="asd","zxc","qwe",'a'
$A2 = "asd","zxc","bqwe",'b'
$A1,$A2 | 
%{
    $_| 
        %{
        If ($A1 -contains $_ -and $A2 -notcontains $_) {$_}
        }
}

      

0


source


$sccm=@(1,2,2,3)   
$wpt=@(2,4)

Compare-Object -ReferenceObject $sccm  -DifferenceObject $wpt | 
    Where-Object { $_.SideIndicator -eq '<=' } | 
    ForEach-Object  { Write-Output $_.InputObject }

      

This will return 1,2,3, this method is incorrect

0


source







All Articles