I can sort an array using the pipeline, like this $array | Sort-object
However, I have found that the pipeline is SLOW, and mostly makes sense in quick one liners. But when writing a program, or even a quick script, I find it's better to not use the pipeline, for both readability and performance reasons. So I went to SS64 and found this page on Sort-Object with mention of the-InputObject parameter. And I would have thought that Sort-Object -InputObject:$array would be the same. But no, that page specifically says of -InputObject
The objects to be sorted.
When the
-InputObjectparameter is used to submit a collection of items,Sort-Objectreceives one object that represents the collection. Because one object cannot be sorted,Sort-Objectreturns the entire collection unchanged.To sort objects, pipe them to
Sort-Object.
So, what on earth is -InputObject for then? It seems like the only possible use case is the one that doesn't work.
And, IS there a way to use Sort-Object on an existing array, without resorting to the pipeline?
Sort-Object -InputObjectis meant to be used from the pipeline, not invoked as a direct argument. Use-InputObjectlike so:When you pass a collection via the pipeline, each element is sent to the cmdlet as it becomes available. The collection is unrolled and each element is processed individually by the cmdlet.
When you invoke the argument directly, the collection is not unrolled. so in the case of
ForEach-Objectrather than sorting the several elements individually it sees a single object and returns just that object. Yes, it's a collection, but the cmdlet is designed to use the unrolling mechanic of the PowerShell pipeline, it is not designed to unroll the collection itself.It can be a bit confusing, and to make it clear as mud many cmdlets work fine when the pipeline argument is directly invoked (often
-InputObjectbut other names are also used). But as a rule of thumb if-InputObject(or whatever theValueFromPipelineparameter is named) takes a collection, I invoke it using the pipeline.If you want a faster sort method, you can use the
Array.Sortstatic method instead:Array.ForEachalso performs faster thanForEach-Objector theforeachstatement, andArray.Whereperforms better thanWhere-Object. The trade-off with using theArraystatic methods is you have a chink in the pipeline chain, as you can't pipe data into a .NET method.To address your concern about relying on
Sort-Object -Unique, you can pipe the result ofArray.SorttoSelect-Object -Uniqueinstead. For example:will output a sorted collection with unique values: