Home > Blockchain >  Join two objects - cannot add a member with the name "x" because a member with that name a
Join two objects - cannot add a member with the name "x" because a member with that name a

Time:11-15

The following code joins data and data2 and creates a denormalized CSV file.

$str = '{
    "data": [
        { "attrs": { "id": "A", "more": "A" }, 
          "relations": [{"id": "r11"}, {"id": "r12"}] },
        { "attrs": { "id": "B", "more": "B" }, 
          "relations": [{"id": "r21"}] }
    ],
    "data2": [
        {"id": "r11", "attrs": { "x": "11", "y": "1"}},
        {"id": "r12", "attrs": { "x": "12", "y": "2"}},
        {"id": "r21", "attrs": { "x": "21", "y": "1"}}
    ]}'
$json = $str | ConvertFrom-Json

$json.data | 
% {
    #$data = $null
    $data = $_.attrs
    $_.relations.id | #select -first 1 | 
    % {
        $d2 = $json.data2 | ? id -eq $_ | select -ExpandProperty attrs
        Write-Host -ForegroundColor Green $d2
        $d2 | Get-Member -Type Properties | % {
            Write-Host -ForegroundColor Red $_
            Add-Member -InputObject $data -NotePropertyName $_.Name -NotePropertyValue $_
        }
        $data
    } 
} | 
ConvertTo-Csv

However, it got the following error?

Add-Member: 
Line |
  12 |              Add-Member -InputObject $data -NotePropertyName $_.Name - …
     |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | Cannot add a member with the name "x" because a member with that name already exists. To overwrite the member anyway, add the Force parameter to your command.
string y=1

CodePudding user response:

Because each attrs in data could have multiple relation.ids, you adding the attrs (Add-Member) twice to the d2 object, therefore you will need to unravel the data object first (see my answer to your previous question: Zip two select list? to create flat $data and $data2 objects).
As explained in a few answers of In PowerShell, what's the best way to join two tables into one?, it is probably easiest and fastest to use an hashtable:

$Hashtable = @{}
$Data2.ForEach{ $Hashtable[$_.id] = $_}

$Hashtable

Name                           Value
----                           -----
r12                            @{id=r12; x=12; y=2}
r21                            @{id=r21; x=21; y=1}
r11                            @{id=r11; x=11; y=1}

Than add the properties to the $data objects:

$data.ForEach{
     $_ |Add-Member -NotePropertyName x -NotePropertyValue $HashTable[$_.relation].x
     $_ |Add-Member -NotePropertyName y -NotePropertyValue $HashTable[$_.relation].y
}

$data |Format-Table

relation id more x  y
-------- -- ---- -  -
r11      A  A    11 1
r12      A  A    12 2
r21      B  B    21 1

In case you do not want to reinvent the wheel, you might as well use the Join-Object script/Join-Object Module my answer:

$data |Join $data2 -on relation -eq id |Format-Table

relation id more x  y
-------- -- ---- -  -
r11      A  A    11 1
r12      A  A    12 2
r21      B  B    21 1
  • Related