ScriptMonkey
ScriptMonkey

Reputation: 311

Powershell elegantly enumerate several variables

I have a text output which shows the runtimes of each selection I make in a script.

Check Level: 0, 38.99607466333333

Check Level: 1, 60.93540646055553

etc.

What I'd like to do is have some read-host lines, showing a choice of what level I'd like to go to, and next to that the variable showing how long on average it takes, i.e. 'Checklevel 1 takes 60 minutes'.

The following script works, but I can't help thinking there's a better alternative:

$CheckLevel0 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 0,*"}
$CheckLevel1 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 1,*"}
$CheckLevel2 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 2,*"}
$CheckLevel3 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 3,*"}
$CheckLevel4 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 4,*"}
$CheckLevel5 = Get-Content $RuntimeFile | Where {$_ -like "Check Level: 5,*"}

Ideally, I'd expect to have all the $CheckLevelx variables populated with one or two lines... I've tried all sorts.

Upvotes: 0

Views: 41

Answers (1)

vonPryz
vonPryz

Reputation: 24071

Whlist gvee's solution is simple and elegant, it doesn't work if you'd like to show a menu that shows execution times too.

That being said, you are right on the track about simpler a solution. Whenever one has more than, say, three variables named value0, value1, ... valuen, it's usually time to use a data structure. An array would be an obvious choice, quite often a hashtable would do too. Via .Net, there are many types for more special needs.

If you need to do more complex processing with the data file, consider preprocessing it. Let's use a regex and hashtable like so,

# Some dummy data. Note the duplicate entry for level 1
$d = ('Check Level: 0, 38.99607466333333',` 
'Check Level: 1, 60.93540646055553',`
'Check Level: 2, 34.43543543967473',`
'Check Level: 1, 99.99990646055553')

# A regular expression to match strings
$rex = [regex]::new('Check Level: (\d+),.*')

# Populate a hashtable with contents
$ht = @{}
$d | % {
    $level = $rex.Match($_).groups[1].value
    $line = $rex.Match($_).groups[0].value
    if( $ht.ContainsKey($level)) {
        # Handle duplicates here.
        $ht[$level] = $line
    }
    else {
        $ht.Add($level, $line)
    }
}
# Print the hashtable in key order.
$ht.GetEnumerator() | sort

Name                           Value
----                           -----
0                              Check Level: 0, 38.99607466333333
1                              Check Level: 1, 99.99990646055553
2                              Check Level: 2, 34.43543543967473

Upvotes: 1

Related Questions