I know PowerShell is mostly case insensitive, but when using both -AsHashTable
and -CaseSensitive
I expected to end up with a case sensitive hashtable.
$capitonyms = @(
[PSCustomObject]@{
Capitonym = 'Bill'
}
[PSCustomObject]@{
Capitonym = 'bill'
}
)
$capitonyms | Group-Object Capitonym -AsHashTable -CaseSensitive
Name Value
---- -----
Bill {@{Capitonym=Bill}}
bill {@{Capitonym=bill}}
Group-Object : The objects grouped by this property cannot be expanded because there is a key duplication. Provide a valid value for the property, and then try again.
At line:1 char:15
+ $capitonyms | Group-Object Capitonym -AsHashTable -CaseSensitive
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Group-Object], Exception
+ FullyQualifiedErrorId : The objects grouped by this property cannot be expanded because there is a key duplication. Provide a valid value for the property, and then try again.,Microsoft.PowerShell.Commands.GroupObjectCommand
Name Value
---- -----
PSVersion 7.0.0-preview.3
PSEdition Core
GitCommitId 7.0.0-preview.3
OS Microsoft Windows 10.0.18362
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Seems completely reasonable to me.
@SteveL-MSFT This would be a breaking change. If there are no key conflicts, current users may depend on the case-insensitivity of the generated hashtable. (Also note - since this cmdlet was envisioned as grouping objects by .NET property name, the notion of two properties with the same name differing by case is not the common case.)
@lahell Given that this is a breaking change, what is the rational for doing this? That is, what scenarios are unblocked, what important thing can you do that you couldn't do before? Providing these scenarios helps the Committee make decisions about this sort of thing. Thanks!
Why would anyone use both CaseSensitive and AsHashTable if they need a case insensitive hashtable?
I noticed this when grouping AD users by department to look for typos and was not sure if this was intentional behaviour.
This is not a big deal for me. I got the hashtable I needed with the following code.
$hashtable = New-Object System.Collections.Hashtable
$capitonyms | foreach { $hashtable[$_.Capitonym] += ,$_ }
$hashtable
Agree with @BrucePay that it would be good to understand what the real world scenario that is impacted by this. However, this doesn't have to be a breaking change, it could be a new switch to make it explicit.
I mean, if -CaseSensitive
doesn't _already_ make it explicit, we're kind of out of options for making it explicit. 馃槀
since this cmdlet was envisioned as grouping objects by .NET property name
Grouping happens by property _value_, not _name_, and given that omitting -AsHashtable
already works exactly as advertised:
PS> $capitonyms | Group-Object Capitonym -CaseSensitive
Count Name Group
----- ---- -----
1 bill {@{Capitonym=bill}}
1 Bill {@{Capitonym=Bill}}
so should the variant with -AsHashtable
.
So I don't see a breaking change here, only a bug fix.
Users who opt for combining -CaseSensitive
with -AsHashtable
will have to be aware that the resulting hashtable will have case-sensitive key lookups, unlike regular PowerShell hashtables, but since -CaseSensitive
is an explicit opt-in, that seems reasonable.
My real world scenario was just using it to clean up human errors in department names.
I guess this could be more of an issue on Linux. This simple test ends in key duplication error.
$dir1 = New-Item -Name test -Type Directory
$files1 = 1..3 | foreach { New-Item -Path $dir1.FullName -Name "file$_" -Type File }
$dir2 = New-Item -Name TEST -Type Directory
$files2 = 1..3 | foreach { New-Item -Path $dir2.FullName -Name "file$_" -Type File }
Get-ChildItem -Recurse | group DirectoryName -AsHashTable
:tada:This issue was addressed in #11030, which has now been successfully released as v7.0.0-preview.6
.:tada:
Handy links:
Thanks @vexx32, I ran a few tests in preview 6 and your fix works great.
I did notice that adding a $null
to the mix gives a misleading error message.
$capitonyms = @(
[PSCustomObject]@{
Capitonym = 'Bill'
}
[PSCustomObject]@{
Capitonym = 'bill'
}
[PSCustomObject]@{
Capitonym = $null
}
)
$capitonyms | Group-Object Capitonym -AsHashTable -CaseSensitive
The code above will throw the error message:
Group-Object: The objects grouped by this property cannot be expanded because there is a key duplication. Provide a valid value for the property, and then try again.
The InnerException is:
System.ArgumentNullException: Key cannot be null. (Parameter 'key')
at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
at Microsoft.PowerShell.Commands.GroupObjectCommand.EndProcessing()
@lahell Please open new issue.
Most helpful comment
Grouping happens by property _value_, not _name_, and given that omitting
-AsHashtable
already works exactly as advertised:so should the variant with
-AsHashtable
.So I don't see a breaking change here, only a bug fix.
Users who opt for combining
-CaseSensitive
with-AsHashtable
will have to be aware that the resulting hashtable will have case-sensitive key lookups, unlike regular PowerShell hashtables, but since-CaseSensitive
is an explicit opt-in, that seems reasonable.