Sort Hashtable with Arrays as values

Question:

Description: I’m building a PowerShell-script that searches for files, then gives them unique names, copies them and then verifies them via hash-calculation – I chose to split the script in functions for each step, so it’s easier to maintain the whole thing.
To get all values from one function to the other, I chose to use [hashtable]$FooBar – inside $FooBar, there are multiple arrays, such as FullName or OutputPath (which may change per file as they will be copied to subfolders named yyyy-mm-dd). All arrays are correlating with each other (meaning that index 1 contains all values of the first file, index 2 the values for the second file,…) and this works fine as of now.

A short simplified visualisation:

However, I now need to sort them all by one value-set of one of the arrays, e.g. the size. Or, visualised again:

I tried $FooBar.GetEnumerator() | Sort-Object -Property Size, but this does not change anything. Google turned up suggestions on how to sort an array of hashtables, but in my case, it’s the other way round, and I can’t get my head around this because I don’t even understand why this is a problem in the first place.

So my question is: is there any way to sort all arrays inside the hashtable by the value-set of one of the arrays? I can’t get my head around this.

Disclaimer: I’m a PowerShell-autodidact with no reasonable background in scripting/programming, so it might well be that my “include everything in one hashtable”-solution isn’t going to work at all or might be extremely inefficient – if so, please tell me.

Answer:

The easiest way to go about what I believe you are trying to do is Select-Object

This will create an array of new objects that only have the desired properties. The reason this works and your method doesn’t is because Sort-Object works on properties and the property you are specifying is behind a few layers.

If you need more flexibility than just exact properties, you can create your own like this

Or manually create new properties with the [PSCustomObject] type accelerator:

Update

If you need to add additional properties to the object after it’s initially created you have a few options.

Add-Member

The most common method by far is by using the Add-Member cmdlet.

Something important to keep in mind is that by default this cmdlet does not return anything. So if you place the above statement at the end of a function and do not separately return the object, your function won’t return anything. Make sure you either use the -PassThru parameter (this is also useful for chaining Add-Member commands) or call the variable afterwards (like the example above)

Select-Object

You can select all previous properties when using calculated properties to add members. Keep in mind, because of how Select-Object works, all methods from the source object will not be carried over.

psobject.Properties

This one is my personal favorite, but it’s restricted to later versions of PowerShell and I haven’t actually seen it used by anyone else yet.

Each member type has it’s own constructor. You can also add methods to $fooBar.psobject.Methods or either type to $fooBar.psobject.Members. I like this method because it feels more explicit, and something about adding members with members feels right.

Summary

The method you choose is mostly preference. I would recommend Add-Member if possible because it’s the most used, therefore has better readability and more people who can answer questions about it.

I would also like to mention that it’s usually best to avoid adding additional members if at all possible. A function’s return value should ideally have a reliable form. If someone is using your function and they have to guess when a property or method will exist on your object it becomes very difficult to debug. Obviously this isn’t a hard and fast rule, but if you need to add a member you should at least consider if it would be better to refactor instead.

Source:

Sort Hashtable with Arrays as values by licensed under CC BY-SA | With most appropriate answer!

Leave a Reply