Conditional Property After Powershell Left Join

45 Views Asked by At

When I do a left join on two objects via Powershell I define a property 'Name'. I want the property to have the value of the 'Name' field in the right object if the record exists and the value of the 'Name' field in the left object if it does not.

I have tried various conditional statements like

@{ Name = If($Right.Length -eq 0){'Left.Name'}else{'Right.Name'}}
@{ Name = If($Right -eq $null){'Left.Name'}else{'Right.Name'}}
@{ Name = If($null -eq $Right){'Left.Name'}else{'Right.Name'}}

but every conditional statement I've tried either always evaluates true or always evaluates false.

Obviously, I'm missing something. How do I do this?

Begin edit:

$objectA = @(
@{
"Id"="1"
"Name"="Bob"
}, 
@{
"Id"="2"
"Name"="Bill"
},
@{
"Id"="3"
"Name"="Ted"
}
) 


$objectB = @(
@{
"Id"="2"
"Name"="John"
}
) 

$objectA | leftjoin $objectB -On Id -Property @{ID = 'Left.ID'}, @{Name = If($Right -ne $null){'Left.Name'}else{'Right.Name'}}|Format-Table

I want the output to look like:

ID Name
-- ----
1  Bob    
2  John
3  Ted
2

There are 2 best solutions below

1
Santiago Squarzon On

Unclear what leftjoin is but assuming it works similarly to calculated properties for Select-Object this does the trick:

$objectA = @(
    [pscustomobject]@{
        'Id'   = '1'
        'Name' = 'Bob'
    },
    [pscustomobject]@{
        'Id'   = '2'
        'Name' = 'Bill'
    },
    [pscustomobject]@{
        'Id'   = '3'
        'Name' = 'Ted'
    }
)

$objectB = @(
    [pscustomobject]@{
        'Id'   = '2'
        'Name' = 'John'
    }
)

# assuming `$objectB` is an array of mutliple objects
# you will want a hashtable here for fast lookups,
# `Group-Object -AsHashtable` is an easy and efficient way to create one
$objectBMap = $objectB | Group-Object Id -AsHashTable -AsString
$objectA | Select-Object @(
    'Id'
    @{ 
        Name       = 'Name'
        Expression = {
            # if the Id from left exists in the right
            if ($objectBMap.ContainsKey($_.Id)) {
                # use the Name from the right
                return $objectBMap[$_.Id].Name
            }
            # else, use the Name from the left
            $_.Name
        }
    })
1
Jim Davis On

My problem was that the objects $Right and $Left are not exposed unless they are in a script block so the way to get the desired output in my example is:

$objectA = @(
@{
"Id"="1"
"Name"="Bob"
}, 
@{
"Id"="2"
"Name"="Bill"
},
@{
"Id"="3"
"Name"="Ted"
}
) 


$objectB = @(
@{
"Id"="2"
"Name"="John"
}
) 

$objectA | leftjoin $objectB -On Id -Property @{ID = 'Left.ID'}, @{Name = {if($Right['Name'] -ne $null){$Right['Name']}else{$Left['Name']}}}|Format-Table