# encoding: ascii
# api: powershell
# title: Join-Objects
# description: Performs a join of all properties from two objects. Supports scriptblock evaluation, pipeline joining, etc.
# version: 3.0
# type: script
# author: Joel Bennett
# license: CC0
# function: Join-Object
# x-poshcode-id: 1818
# x-derived-from-id: 6598
# x-archived: 2017-05-22T01:57:05
# x-published: 2010-05-03T13:53:00
#
# ls | Join-Object { $_ | Select BaseName } { $_.LastWriteTime } | ft -auto
#
<#
.Synopsis
Performs a join of all properties from two objects
.Description
Joins the properties of two or more objects together to produce a single custom object
Support scriptblock evaluation, and joining objects from the pipeline
.Example
ls | Join-Object { $_ | Select BaseName } { $_.LastWriteTime }
#>
#Packaged as a script. Uncomment this top and bottom function {...} lines to embed with other functions.
#function Join-Object {
[CmdletBinding(DefaultParameterSetName="OneTwo")]
PARAM(
[Parameter(Position=0, Mandatory=$false)]
$First
,
[Parameter(Position=1, Mandatory=$false)]
$Second
,
[Parameter(ValueFromPipeline=$true, Mandatory = $true, ParameterSetName="FromPipeline")]
$InputObject
,
[Switch]$Quiet
)
BEGIN {
if($First -and $First -isnot [ScriptBlock]) {
Write-Verbose "Setting Output = $First"
$Out1 = $First
[string[]] $p1 = $First | gm -type Properties | select -expand Name
$Output = $Out1 | Select $p1
} else {
$Output = $null
}
}
PROCESS {
if(!$InputObject -and $Second) {
$Out2 = $Second
} elseif($Second -is [ScriptBlock]) {
$Out2 = $InputObject | &$Second
} elseif(!$Second) {
$Out2 = $InputObject
}
if($First -is [ScriptBlock]){
$Out1 = $InputObject | &$First
[string[]] $p1 = $Out1 | gm -type Properties | select -expand Name
$Output = $Out1 | Select $p1
} elseif($First) {
[string[]] $p1 = $First | gm -type Properties | select -expand Name
$Output = $First | Select $p1
} elseif(!$Output) {
Write-Verbose "Initializing Output From Pipeline = $InputObject"
[string[]] $p1 = $InputObject | gm -type Properties | select -expand Name
$Output = $InputObject | Select $p1
return
} else {
## ToDo: this is lazy. Chache it.
[string[]] $p1 = $Output | gm -type Properties | select -expand Name
}
if($Out2) {
$p2 = @($Out2 | gm -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name)
Write-Verbose "Merging $($p2.Count) into the output (which already has $(($Output | gm -type NoteProperty).Count) properties)."
if(!$Quiet) {
[string[]]$ignored = $Out2 | gm -type Properties | Where { $p1 -contains $_.Name } | select -expand Name
if($Ignored) {
Write-Warning "Ignoring $($ignored.Count) values which are already present:`n$($out2 | fl -Property $ignored | out-string)"
}
}
foreach($p in $p2) {
$Output = Add-Member -in $Output -type NoteProperty -name $p -value $Out2.$p -Passthru
}
}
}
END {
$Output
}
#}