Pergunta

PowerShell 3.0 CTP1 introduces a new feature [ordered] which is somewhat a shortcut for OrderedDictionary. I cannot imagine practical use cases of it. Why is this feature really useful? Can somebody provide some useful examples?

Example: this is, IMHO, rather demo case than practical:

$a = [ordered]@{a=1;b=2;d=3;c=4}

(I do not mind if it is still useful, then I am just looking for other useful cases).

I am not looking for use cases of OrderedDictionary, it is useful, indeed. But we can use it directly in v2.0 (and I do a lot). I am trying to understand why is this new feature [ordered] needed in addition.


Collected use cases from answers:

$hash = [ordered]@{}

is shorter than

$hash = New-Object System.Collections.Specialized.OrderedDictionary

N.B. ordered is not a real shortcut for the type. New-Object ordered does not work.

N.B. 2: But this is still a good shortcut because (I think, cannot try) it creates typical for PowerShell case insensitive dictionary. The equivalent command in v2.0 is too long, indeed:

New-Object System.Collections.Specialized.OrderedDictionary]([System.StringComparer]::OrdinalIgnoreCase)
Foi útil?

Solução

First I will start by asking - Why not have them?

I can think of a use case in my project where we use Powershell scripts for build and deploy and yml for config ( using https://github.com/scottmuc/PowerYaml )

The config from yml is read in as hashtables. The tasks are specified in the yml like deploy to database, deploy to iis, deploy service and so on. I would like to do the database deploy and then website deploy so that I can avoid iisreset afterwards. Currently I have to explicitly look at that. Now, I can have an Ordered hash table and specify the deploy database first and hence it happens first.

Snippet:

function Convert-YamlMappingNodeToHash($node)
{
    $hash = @{}
    $yamlNodes = $node.Children

    foreach($key in $yamlNodes.Keys)
    {
        $hash[$key.Value] = Explode-Node $yamlNodes[$key]
    }
    return $hash
}

Now the $hash =@{} become $hash=[ordered]@{}

I don't know how this means for a bloated product. OrderedDictionary is there in .NET ( I have lots of use cases for it in programming ) and they have just added an accelerator for it.

Outras dicas

This is actually particularly useful for creating on-the-fly objects sorta like how you would use ExpandoObject in C# or dynamic objects in JavaScript. The problem with doing this in prior versions of PowerShell is that @{} (which becomes a regular HashTable) loses your ordering of keys so it's a huge PITA to display these to the screen.

Consider this.

foreach ($row in import-csv blah.csv) {

  # In v3: $obj = [Ordered]@{

  $obj = @{
    Name      = $row.Name
    Exists    = Test-Path $row.FileName
    OtherProp = 123
    Blah      = "derp"
    Timestamp = Get-Date
  }

  New-Object PSObject -Property $Obj

}

In PowerShell v2, the column order is unpredictable because the Hashtable does not retain the order of the keys. In PowerShell v3, if you used the [Ordered] type, the key order is retained, making the quick and dirty PowerShell syntax almost as convenient as JSON for quickly building up object structures without all the overhead and performance issues associated with Add-Member or Select-Object.

Not coincidentally, there is another addition to PowerShell v3. Similar to [Ordered] you can actually specify [PSCustomObject] instead. This will create an actual PSObject right from the start instead of requiring a separate call to New-Object. I can't say for sure but I am pretty sure that [Ordered] was a side effect of the changes they made to the parser to make that happen. If they were just doing a conversion from a regular Hashtable, there'd be no way to restore the original order of the keys.

This is useful for doing a SQL join (aka merging or zipping) two data files. Maybe the files are CSV or JSON.

You'd want to build a hashtable from the first file, merge in or use data from the second file, then stream the changes back out to disk or to the next step of the script.

With [ordered] you can keep the same order of the original file, but still use it like a hashtable.

I've seen it used in powershell scripts that build tabs of information and sort the tabs. For example, retrieving hard drive information from several servers, each server in its own tab, then sorting the tabs by server name before saving. The "tab sort" code looks like this:

$i=0;$wb.Worksheets | %{$i++;[ordered]@{$_.name=$i}}

-Gill

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top