3

i'm trying to verify if an object exist in a list imported from 2 CSV files I get an error even though the 2 objects are similar

$CSV1 = Import-CSV $path $delimiter $header
$CSV2 = Import-CSV $path2 $delimiter $header


$myList = New-Object -TypeName 'System.Collections.ArrayList';
$myList.add("") | Out-Null
Foreach($value in $CSV1)
{
    $obj = $value.PSObject.Copy()
    $obj.Name = GetNameRef($value.Name)
    $obj.IP = GetIPRef($value.IP)
    if(!($CSV2.contains($obj)))
    {
        $myList.Add($value)|Out-Null
    }
}

$myList | Format-Table * | Out-File ".\Result.txt"

So when i check manually i found a object in CSV2 with the same value for all properties but when i do CSV2.Contains, He didn't return "True"

I know it's like a reference problem but i didn't found any information about that actually or only to compare 1 propertie

The both CSV file has the same template like

First CSV file :

Name,ServerName,IP,Mono 
Luc,PM45,255.245.22.21,MonoY 
Ced,PC78,245.222.1.12,MonoX 

Second CSV file

Name,ServerName,IP,Mono 
John,PM45,255.245.22.20,MonoY 
Dab,PC75,245.222.11.12,MonoX 

In my project for exemple The value Luc and John with IP 255.245.22.21 and 255.245.22.20 refer to the same value, I found reference with GetNameRef() and GetIpRef()

So I modify some value to see if exist in the second CSV file But all value don't have equivalent in second CSVfile and i want found them

Exemple : i have $object1 with value of the first line of CSV file1
i have $object2 with value of the first line of CSV file2
so i have :

$object1 :
Name = Luc,
ServerName = PM45,
IP = 255.245.22.21,
Mono = MonoY

$object2:
Name = John,
ServerName = PM45,
IP = 255.245.22.20,
Mono = MonoY

Now $obj take value of $object1 and i modify Name and IP to obtain this

$object1 :
Name = Luc,
ServerName = PM45,
IP = 255.245.22.21,
Mono = MonoY

$object2:
Name = John,
ServerName = PM45,
IP = 255.245.22.20,
Mono = MonoY

$obj :
Name = John,
ServerName = PM45,
IP = 255.245.22.20,
Mono = MonoY

So $obj and $object2 have same value properties

Aomichi
  • 57
  • 5
  • `pscustomobject`s are not comparable. You need to write your own logic for that – Santiago Squarzon Dec 28 '22 at 13:45
  • 1
    Show us a few lines of both CSV files as [Formatted](https://stackoverflow.com/help/formatting) text so we know what we're dealing with. Why do you hardcode the name 'John' and the IP '255.255.255.255' in there? – Theo Dec 28 '22 at 13:50
  • Please don't add this information in the comment section, add it to your question instead – Santiago Squarzon Dec 28 '22 at 14:02
  • How sorry , i have edit my post – Aomichi Dec 28 '22 at 14:09
  • 1
    So, what would you consider `equal` values? Which fields would you use for that? Obviously not all, because the IP's don't match anywhere.. – Theo Dec 28 '22 at 14:13
  • I have add a exemple – Aomichi Dec 28 '22 at 14:28
  • I see what you mean, by updating the values of the objects in your loop you're ensuring at least one of the objects is structurally equal to one on the other CSV. That's fine but, are you looking to compare all properties from these objects to see if they're equal or is there just a specific set of properties you need to check? If you want to compare all, it make take time depending on how big these CSVs are – Santiago Squarzon Dec 28 '22 at 14:31
  • I need to compare all properties. In fact, if after changing the name and the IP I do not find a result in the second CSV, it means that it is a specificity of my first CSV and it needs to be added to the result I have something like 300 000 value in both CSV, i know that take some minutes to compare but it's just a "Beta" for my project – Aomichi Dec 28 '22 at 14:39
  • Using this [`Join-Object script`](https://www.powershellgallery.com/packages/Join)/[`Join-Object Module`](https://www.powershellgallery.com/packages/JoinModule) (see also: [In Powershell, what's the best way to join two tables into one?](https://stackoverflow.com/a/45483110/1701026)): `Import-CSV $path $delimiter $header |Join (Import-CSV $path2 $delimiter $header) -on *` – iRon Dec 28 '22 at 16:53

1 Answers1

2

The easiest way you can handle this is probably using ValueTuple or Tuple, both structures are structurally comparable. You can then use a HashSet<T> to filter those objects that appear in CSV1 and CSV2.

Note that this code assumes 2 things:

  1. The objects from both CSVs have the same Property Names (same Column Names).
  2. The objects have 8 properties or less (this is a Tuple and ValueTuple limitation).
$hash = [System.Collections.Generic.HashSet[object]]::new()

foreach($line in Import-Csv path\to\csv1.csv) {
    $null = $hash.Add([ValueTuple]::Create.Invoke($line.PSObject.Properties.Value))
}

Import-Csv path\to\csv2.csv | & {
    process {
        if(-not $hash.Add([ValueTuple]::Create.Invoke($_.PSObject.Properties.Value))) {
            $_
        }
    }
} | Export-Csv path\to\objectsInBothCsvs.csv -NoTypeInformation
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37