Add multiple instances of a noteproperty to an object

Hello all,

I’ve got a list of ADSiteNames and Subnets. My ideal output is:

Name:       SiteName
  Subnets:       subneta
                 subnetb
                 subnetc

So that I could pipe this on to a further command and do somethning with each subnet. I can’t quite think of the formatting, so as I workaround I’ve come up with this, in which I add a SubNet$i noteproperty to the object with each iteration of a for loop. It works but is so very ugly, and working with the output later is dodgy at best.

$sites = Import-Csv -Delimiter ";" .\AdSitestoSubnets.csv
#$sites | Select-Object -Unique Site

$unique_sites = @()

ForEach ($site in ($sites | Select-Object -Unique Site)){
    
    $obj = New-Object PSObject -Property @{
            Name   = $site.site
            }
    $i = 0        
    $sites | Where-Object Site -eq $site.Site | ForEach-Object {
        $obj | Add-Member -NotePropertyName "SubNet$i" $_.SubNet
        $i++
        }

        $unique_sites += $obj
        
    }


Name     : USLouisville
SubNet0  : 10.1.128.0
SubNet1  : 10.14.0.0
SubNet2  : 10.16.0.0
SubNet3  : 10.16.10.0
SubNet4  : 10.16.10.0
SubNet5  : 10.16.100.0
SubNet6  : 10.16.90.0
SubNet7  : 10.220.16.0
SubNet8  : 10.220.18.0
SubNet9  : 10.220.20.0
SubNet10 : 10.220.46.0
SubNet11 : 10.221.38.0
SubNet12 : 10.3.0.0

Name    : USHouston
SubNet0 : 10.1.137.0
SubNet1 : 10.220.188.0
SubNet2 : 10.220.49.0


If you have to do this task, how would you do it? I’d consider my solution to be very, very ugly, even if it works. I’m hoping you guys can show me a new construct or method of doing this.

hi,

Kind of hard when we don’t have the “source-data” of your $sites variable :slight_smile: You could use the export-clixml cmdlet next time and add the xml from that as a file attatchment. That way we can import it and play with it easy.

If I understand you correctly, here is what I would do:

# Create dummy data $sites = @() 1..2 | foreach { $site = "" | select Site, Subnet $site.site ="Houston" $site.Subnet = "10.0.$_.0" $sites += $site } 1..4 | foreach { $site = "" | select Site, Subnet $site.site ="USLouisville" $site.Subnet = "10.$_.0.0" $sites += $site } $sites should now contain this:

Site Subnet


Houston 10.0.1.0
Houston 10.0.2.0
USLouisville 10.1.0.0
USLouisville 10.2.0.0
USLouisville 10.3.0.0
USLouisville 10.4.0.0

Now if you do this:

$UniqueSites = @()
foreach($site in ($sites | select -Unique site))
{
$LevelOne = “” | select SiteName,Subnet
$levelOne.SiteName = $site.site
$levelOne.Subnet = @()
foreach($singleSite in ($sites | where {$_.site -eq $site.site}))
{
$LevelOne.subnet += $singleSite.subnet
}
$UniqueSites += $LevelOne
}

$UniqueSites will now produce this:

SiteName Subnet


Houston {10.0.1.0, 10.0.2.0}
USLouisville {10.1.0.0, 10.2.0.0, 10.3.0.0, 10.4.0.0}

Does it make sense?

Cheers

Tore

It sounds like what you want is an object that has a string property (site name), and an array property (Subnets). Anytime you find yourself creating properties or variables named Thingy1, Thingy2, etc, it’s a sure sign that you should actually be dealing with some sort of array or collection. You can also shorten the code quite a bit by making use of Group-Object, instead of reinventing that particular wheel yourself with the nested loop:

$sites = Import-Csv -Delimiter ";" .\AdSitestoSubnets.csv

$unique_sites = $sites |
Group-Object -Property Site |
Select-Object -Property @(
    @{ Name = 'Site';    Expression = { $_.Name } }
    @{ Name = 'Subnets'; Expression = { $_.Group | Select-Object -ExpandProperty Subnet } }
)

Tore, thanks for the pointers. My issue was converting from a [string] to an [int] in order to do math functions, hence my ugly code there.

Dave, I’ve never heard of Group object before and I absolutely LOVE it!

Thanks a lot, this is precisely what I needed.

No problem! The -Object cmdlets are mostly pretty useful (though I don’t use Tee-Object much, for whatever reason.) If any of these look unfamiliar to you at this point, I’d suggest checking out their help files when you have some free time, and keep them in your toolbox. :slight_smile: Heck, even if you know them, read the help files anyway; some of them have some sneaky features in parameters or syntax that you might not have known about.

PS C:\Source\temp> Get-Command *-Object

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Compare-Object                                     Microsoft.PowerShell.Utility
Cmdlet          ForEach-Object                                     Microsoft.PowerShell.Core
Cmdlet          Group-Object                                       Microsoft.PowerShell.Utility
Cmdlet          Measure-Object                                     Microsoft.PowerShell.Utility
Cmdlet          New-Object                                         Microsoft.PowerShell.Utility
Cmdlet          Select-Object                                      Microsoft.PowerShell.Utility
Cmdlet          Sort-Object                                        Microsoft.PowerShell.Utility
Cmdlet          Tee-Object                                         Microsoft.PowerShell.Utility
Cmdlet          Where-Object                                       Microsoft.PowerShell.Core