Home > Software engineering >  Sort a dictionary of dictionaries on nested dictionary property
Sort a dictionary of dictionaries on nested dictionary property

Time:09-29

Given an ordered dictionary that contains dictionaries of an arbitrary number of items, I need to sort on the value of one of those items. So

$data = [Ordered]@{
    '1' = @{'thing' = "3"}
    '2' = @{'thing' = "2"}
    '3' = @{'thing' = "1"}
}

sorted on the value of thing would produce the same end result as

$ordered = [Ordered]@{
    '3' = @{'thing' = "1"}
    '2' = @{'thing' = "2"}
    '1' = @{'thing' = "3"}
}

I can sort the first dictionary on it's own keys using .GetEnumerator(), but I am stumped as to how I would sort based on the nested key's value, and yet still grab the item in the outermost dictionary to add to a new [Ordered]. I started with this

$data = [Ordered]@{
    '1' = @{'thing' = "3"}
    '2' = @{'thing' = "2"}
    '3' = @{'thing' = "1"}
}

$ordered = [ordered]@{}
foreach ($item in ($keyStatus.GetEnumerator() | Select-Object Value | Sort-Object -Property Value)) {
    $ordered[$item.Key] = $item.Value
}

but of course that errors at the foreach. I suspect this is going to be a late night face palm moment, but there it is.

And, for anyone, like myself, who prefers an example that makes sense, rather than a minimal example, the real data would look something more like this

$data = [Ordered]@{
    '{GUID}' = @{'DisplayName' = "Program A"; 'DisplayVersion' = '1.2'}
    '{GUID}' = @{'DisplayName' = "Program Z"; 'DisplayVersion' = '0.5'}
    '{GUID}' = @{'DisplayName' = "Program M"; 'DisplayVersion' = '3.4'}
}

where {GUID} would be different actual GUIDs, which is the way I want to structure the data. But I want to then present the data sorted by DisplayName.

CodePudding user response:

As explained in comments, after sorting, it will no longer be an OrderedDictionary but just a collection of DictionaryEntry. If you want to reconstruct it you can follow this logic:

$data = [Ordered]@{
    [guid]::NewGuid() = @{'DisplayName' = "Program A"; 'DisplayVersion' = '1.2'}
    [guid]::NewGuid() = @{'DisplayName' = "Program Z"; 'DisplayVersion' = '0.5'}
    [guid]::NewGuid() = @{'DisplayName' = "Program M"; 'DisplayVersion' = '3.4'}
}

$newDict = [ordered]@{}

$data.GetEnumerator() | Sort-Object { $data[$_.Key]['DisplayName'] } | ForEach-Object {
    $newDict[$_.Key] = $_.Value
}
  • Related