How to get the value only from the Hashtable in PowerShell? - powershell

If I have a hastable $states = #{ 1 = 15; 2 = 5; 3 = 41 }, The result shows
Name Value
---- -----
3 41
2 5
1 15
I used $states.GetEnumerator() | sort value -Descending | select -Last 1 to find the minimum value that I need.
The result is:
Name Value
---- -----
2 5
However, I cannot use the value (5) as a new variable to do a calculation. This is due to the result cotains both name and value. Is there any method to get the minimum value only from the result?

Use the .Values property from the beginning:
$states.Values | Sort-Object -Descending | Select-Object -Last 1
Or expand the .Value property:
$states.GetEnumerator() | sort value -Descending | select -Last 1 -ExpandProperty Value

Related

Powershell Get Hashtable Values

I've got this Hashtable with this values:
Name Value
---- -----
Bayas_palm_stem_A0311.jpg 1
Bayas_palm_stem_A0312.jpg 2
Bukit_Bangkong_area.tiff 1
BY_and_siblings_A0259.jpg 5
Cassava_camp_A0275.jpg 1
Children_A0115.jpg 6
cip_barau_kubak.jpg 1
How can i get only the Name and Value where Value is greater than 1 ?
I'm tryng with this code, but i'm doing something wrong!!!
$RT | Group-Object Name , Value | Where-Object {$RT.Values -gt 1}
Thanks a lot for any help.
Use $hashtable.GetEnumerator() to enumerate the individual name-value pairs in the hashtable:
$RT.GetEnumerator() |Where-Object {$_.Value -gt 1}
Beware that if you assign the resulting pairs to a variable, it's not longer a hashtable - it's just an array of individual name-value pairs.
To create a new hashtable with only the name-value pairs that filter through, do:
$RTFiltered = #{}
$RT.GetEnumerator() |Where-Object {$_.Value -gt 1} |ForEach-Object {$RTFiltered.Add($_.Name, $_.Value)}
Like this:
$RT.getenumerator() | Where-Object {$_.Value -gt 1}
Assuming you have a Hashtable defined like this.
$rt = #{
"Bayas_palm_stem_A0311.jpg " = 1
"Bayas_palm_stem_A0312.jpg " = 2
"Bukit_Bangkong_area.tiff " = 1
"BY_and_siblings_A0259.jpg " = 5
"Cassava_camp_A0275.jpg " = 1
"Children_A0115.jpg " = 6
"cip_barau_kubak.jpg " = 1
}
You can call GetEnumerator() which allows you to iterate through the Hashtable.
Once you've got an enumeration of the members, then your normal PowerShell value comparisons will work.
You can get values greater than 1 like this:
$rt.GetEnumerator() | ? Value -gt 1
Name Value
---- -----
BY_and_siblings_A0259.jpg 5
Children_A0115.jpg 6
Bayas_palm_stem_A0312.jpg 2

How to get a numbered count of different items in powershell

Im using the following powershell query to get a list of disks:
Get-NcDisk | Select-Object -Property model | Sort-Object -Property Model -Descending | foreach {$_.model}
It outputs like below:
X316_SMKRE06TA07
X316_HARIH06TA07
X316_HARIH06TA07
X316_HARIH06TA07
How can I get it to output a numbered count of each type of disk like below:
1 X316_SMKRE06TA07
3 X316_HARIH06TA07
Group-Object will do this for you..
I can't use Get-NcDisk but it may just be:
Get-NcDisk | Select-Object -ExpandProperty model | Group-Object
Example output using a string array:
"X316_SMKRE06TA07","X316_HARIH06TA07","X316_HARIH06TA07","X316_HARIH06TA07" | Group-Object
Count Name Group
----- ---- -----
1 X316_SMKRE06TA07 {X316_SMKRE06TA07}
3 X316_HARIH06TA07 {X316_HARIH06TA07, X316_HARIH06TA07, X316_HARIH06TA07}

Sorting by (custom) expression output

So I have this as my current code:
Get-Process | Sort Valid,ProcessName |
Format-Table #{n='ProcessName';e={$_.ProcessName}},
#{n='Valid';e={if(($_.mainmodule.filename | Get-AuthenticodeSignature).Status -eq 'Valid') {1} else {0}}} -AutoSize
which gives me an output of:
ProcessName Valid
----------- -----
3DG4me 1
Adobe CEF Helper 1
Adobe CEF Helper 1
Adobe Desktop Service 1
AdobeIPCBroker 1
AdobeUpdateService 1
AGSService 1
ApplicationFrameHost 1
audiodg 0
avgnt 1
avguard 1
Avira.ServiceHost 1
Avira.Systray 1
avshadow 1
Calculator 0
CCLibrary 1
....etc etc
Even though I put a sort before I formatted it won't let me sort by Valid, which is an integer. I've tried adding [int] before {1} and {0} but it doesn't seem to be working.
You cannot sort by properties that aren't created until after the sorting happened. Valid is not a property of System.Diagnostic.Process objects. If you want to sort by that calculated property you need to add it before sorting. This insertion is usually done via Select-Object:
Get-Process |
Select-Object ProcessName,
#{n='Valid';e={if(($_.mainmodule.filename | Get-AuthenticodeSignature).Status -eq 'Valid') {1} else {0}}} |
Sort Valid, ProcessName |
Format-Table -AutoSize

How to find duplicate values in powershell hash

Imagine the following hash:
$h=#{}
$h.Add(1,'a')
$h.Add(2,'b')
$h.Add(3,'c')
$h.Add(4,'d')
$h.Add(5,'a')
$h.Add(6,'c')
What query would return the 2 duplicate values 'a' and 'c' ?
Basically I am looking for the powershell equivalent of the following SQL query (assuming the table h(c1,c2):
select c1
from h
group by c1
having count(*) > 1
You could try this:
$h.GetEnumerator() | Group-Object Value | ? { $_.Count -gt 1 }
Count Name Group
----- ---- -----
2 c {System.Collections.DictionaryEntry, System.Collections.DictionaryEntry}
2 a {System.Collections.DictionaryEntry, System.Collections.DictionaryEntry}
If you store the results, you could dig into the group to get the key-name for the duplicate entries. Ex.
$a = $h.GetEnumerator() | Group-Object Value | ? { $_.Count -gt 1 }
#Check the first group(the one with 'c' as value)
$a[0].Group
Name Value
---- -----
6 c
3 c
You can use another hash table:
$h=#{}
$h.Add(1,'a')
$h.Add(2,'b')
$h.Add(3,'c')
$h.Add(4,'d')
$h.Add(5,'a')
$h.Add(6,'c')
$h1=#{}
$h.GetEnumerator() | foreach { $h1[$_.Value] += #($_.name) }
$h1.GetEnumerator() | where { $_.value.count -gt 1}
Name Value
---- -----
c {6, 3}
a {5, 1}
Just a slightly different question:
How to list the duplicate items of a PowerShell Array
But a similar solution as from Frode F:
$Duplicates = $Array | Group | ? {$_.Count -gt 1} | Select -ExpandProperty Name

Count the comma in each line and show the line numbers in a text file

I'm using the following script to get the comma counts.
Get-Content .\myFile |
% { ($_ | Select-String `, -all).matches | measure | select count } |
group -Property count
It returns,
Count Name Group
----- ---- -----
131 85 {#{Count=85}, #{Count=85}, #{Count=85}, #{Count=85}...}
3 86 {#{Count=86}, #{Count=86}, #{Count=86}}
Can I show the line number in the Group column instead of #{Count=86}, ...?
The files will have a lot of lines and majority of the lines have the same comma. I want to group them so the output lines will be smaller
Can you use something like this?
$s = #"
this,is,a
test,,
with,
multiple, commas, to, count,
"#
#convert to string-array(like you normally have with multiline strings)
$s = $s -split "`n"
$s | Select-String `, -AllMatches | Select-Object LineNumber, #{n="Count"; e={$_.Matches.Count}} | Group-Object Count
Count Name Group
----- ---- -----
2 2 {#{LineNumber=1; Count=2}, #{LineNumber=2; Count=2}}
1 1 {#{LineNumber=3; Count=1}}
1 4 {#{LineNumber=4; Count=4}}
If you don't want the "count" property multiple times in the group, you need custom objects. Like this:
$s | Select-String `, -AllMatches | Select-Object LineNumber, #{n="Count"; e={$_.Matches.Count}} | Group-Object Count | % {
New-Object psobject -Property #{
"Count" = $_.Name
"LineNumbers" = ($_.Group | Select-Object -ExpandProperty LineNumber)
}
}
Output:
Count LineNumbers
----- -----------
2 {1, 2}
1 3
4 4