craig
craig

Reputation: 26262

Most-succinct way to search an array of hash tables for a key

Assuming:

$columnArray = @(
  @{Name='COL_A';Type=[int];Measurements=@()},
  @{Name='COL_B';Type=[string];Measurements=@()},
  @{Name='COL_C';Type=[datetime];Measurements=@()}
)

Using the Where-Object command to get COL_B's Measurements array:

($Fields | ? { $_.Name -eq 'COL_B' }).Measurements

Is there a more-succinct way of doing this? Would a nested set of PSCustomObjects be a better approach?

Upvotes: 5

Views: 2288

Answers (4)

Dave Sexton
Dave Sexton

Reputation: 11188

How about this:

$columnArray | % {New-Object PSObject -property $_} | ? {$_.Name -eq 'COL_B'} | Select -ExpandProperty Measurements

It converts each element of the array to an object using the -property flag which saves having to explicitly define the object or use Add-Member

Upvotes: 0

Michael T Simmons
Michael T Simmons

Reputation: 31

If you take this approach:

$Info = [PSCustomObject]@{
  Name = "MyFieldName"
  Size = 15
  Date = Get-Date
}

Then these all work:

 $Info | Select Name, Size 
 $Info | Where ($_.date -gt (Get-Date).AddDays(-1)) 
 $Info | Sort Size -Descending | Select -First 1

You can also put whatever function you're using to populate the data in $Info.

$results = Import-CSV C:\Results.csv 

$items =  Foreach ($item in $results) {
   $thisItem = [PSCustomObject]@{
   Name = $_.name
   Size = $_.size
   Date = $_.date
   }
   $thisItem
}

Upvotes: 3

user4003407
user4003407

Reputation: 22122

If you are interested in looking element by key, than Hashtable will be better approach than array.

$columnHashtable=@{
    COL_A=@{Type=[int];Measurements=@()}
    COL_B=@{Type=[string];Measurements=@()}
    COL_C=@{Type=[datetime];Measurements=@()}
}

With Hashtable you can get Measurements array of COL_B by this command:

$columnHashtable.COL_B.Measurements

And If you want to enumerate all elements in Hashtable, then you can use following command:

$columnHashtable.GetEnumerator()|ForEach-Object ...

In case if order of elements in hash table matters, you could use [ordered] operator before hash table literal to create OrderedDictionary instead of Hashtable.

Upvotes: 3

briantist
briantist

Reputation: 47802

You could modify the array itself with a method to do the finding:

Add-Member -InputObject $columnArray -MemberType ScriptMethod -Name FindCol -Value { param([String]$Column) $this | ? { $_.Name -eq $Column }  }

Then you can do:

$columnArray.FindCol('COL_B').Measurements

Or you can do:

Add-Member -InputObject $columnArray -MemberType ScriptMethod -Name GetMeasurements -Value { param([String]$Column) $this | ? { $_.Name -eq $Column } | Select-Object -ExpandProperty Measurements  }

Then:

$columnArray.GetMeasurements('COL_B')

Upvotes: 4

Related Questions