Answered by:
Windows Powershell  Sort Hashtable by child node
Question

I am using Windows 7 and Powershell 4
I have hashtable of students and associated data that I loop through and generate some HTML reports.
Example hashtable:
$Students = @{}$Students["101"] = @{}
$Students["101"]["StudentName"] = "Cathy"
$Students["102"] = @{}
$Students["102"]["StudentName"] = "Bob"
$Students["103"] = @{}
$Students["103"]["StudentName"] = "Alan"
Currently I can loop through the hashtable by the student ID:
$Students.GetEnumerator()  sort key
I would like to be able to loop through the hash table sorted by the StudentName not ID number.
Any ideas on how to accomplish this?
 Edited by UniquePublicIdentity Monday, January 25, 2016 4:18 PM
Answers

jrv,
I guess maybe I'm using nested hashtables?
I would like to easily reference student data like this in my script: $hashtable.$studentID.StudentName or $hashtable.$studentID.Grade or $hashtable.$StudentID.Contact.$ContactName.PhoneNumbers.$PhoneNumber
Should I revisit how I am generating my hashtable(s) or does my approach need rethought?
Yes  use objects.
$Students = @( [pscustomobject]@{Id=101;StudentName="Cathy"} [pscustomobject]@{Id=102;StudentName="Bob"} [pscustomobject]@{Id=103;StudentName="Alan"} ) $studentssort StudentName $students?{$_.ID eq 102} ($students?{$_.ID eq 102}).StudentName
\_(ツ)_/
 Marked as answer by UniquePublicIdentity Tuesday, January 26, 2016 2:11 PM
All replies


I had searched most of Friday for answers to my question. As soon as I posted my question, I found my answer in "Top Related Threads":
https://social.technet.microsoft.com/Forums/windowsserver/enUS/95fdfef149584d5db39d870f2d773df9/sortingahashtablewithinahashtable?forum=ITCG
Here is the answer to my question:
$Students.GetEnumerator()  SortObject Property @{Expression={$_.Value["StudentName"]}}
 Edited by UniquePublicIdentity Tuesday, January 26, 2016 4:02 PM clarity

$Students = @{} $Students["101"] = @{} $Students["101"]["StudentName"] = "Cathy" $Students["102"] = @{} $Students["102"]["StudentName"] = "Bob" $Students["103"] = @{} $Students["103"]["StudentName"] = "Alan" #Loop through values $students.Values%{$_.StudentName}
\_(ツ)_/

It looks like a hash table of hash tables to me. Which makes sense if there's other values (although i'm not sure that's the way i'd order the data).
I suspect you'll want to post more information about what data that hash table holds and how you want to access it. As it is the only answer I can see is to manually loop through and either build some sort of index or brute forcing it each time.


I'd highly recommend scrapping the hashtable usage and just use objects instead.
If you have to deal with preexisting data, do something like this:
$Students = @{} $Students["101"] = @{} $Students["101"]["StudentName"] = "Cathy" $Students["102"] = @{} $Students["102"]["StudentName"] = "Bob" $Students["103"] = @{} $Students["103"]["StudentName"] = "Alan" $obj = $Students.GetEnumerator()  Select @{N='ID';E={$_.Name}},@{N='StudentName';E={$_.Value["StudentName"]}} $obj  Sort StudentName

I had searched most of Friday for answers to my question. As soon as I posted my own question, I my answer in "Top Related Threads":
https://social.technet.microsoft.com/Forums/windowsserver/enUS/95fdfef149584d5db39d870f2d773df9/sortingahashtablewithinahashtable?forum=ITCG
Here is the answer to my question:
$Students.GetEnumerator()  SortObject Property @{Expression={$_.Value["StudentName"]}}
Yes  if you want to sort all of the hashes and not just the data then this is how. I assumed incorrectly that you just wanted to sort the student names.
\_(ツ)_/

jrv,
I guess maybe I'm using nested hashtables?
I would like to easily reference student data like this in my script: $hashtable.$studentID.StudentName or $hashtable.$studentID.Grade or $hashtable.$StudentID.Contact.$ContactName.PhoneNumbers.$PhoneNumber
Should I revisit how I am generating my hashtable(s) or does my approach need rethought?

jrv,
I guess maybe I'm using nested hashtables?
I would like to easily reference student data like this in my script: $hashtable.$studentID.StudentName or $hashtable.$studentID.Grade or $hashtable.$StudentID.Contact.$ContactName.PhoneNumbers.$PhoneNumber
Should I revisit how I am generating my hashtable(s) or does my approach need rethought?
Yes  use objects.
$Students = @( [pscustomobject]@{Id=101;StudentName="Cathy"} [pscustomobject]@{Id=102;StudentName="Bob"} [pscustomobject]@{Id=103;StudentName="Alan"} ) $studentssort StudentName $students?{$_.ID eq 102} ($students?{$_.ID eq 102}).StudentName
\_(ツ)_/
 Marked as answer by UniquePublicIdentity Tuesday, January 26, 2016 2:11 PM



Thanks for the help everyone. I got my script working with what I posted, but with input I received from you, I plan to convert to objects instead.
Hashes are lightweight and useful but, for any complex data a customobject or a datatabe is much more powerful. A custom object,as yu can see, can be easily generated from a hash
$p=@{
Name='Joe'
Age=12
ID='H34B3'
Grade='A+'
Teacher='Mr, Jones'
}[pscustomobject@p
\_(ツ)_/