How would you generate a unique sequence from 000 to 9ZZ. Lastly, my export-csv is not working. Please see the data and export output below.
The alphanumeric sequence starts from 0 through 9 and then A through Z.
Please be advised, my PowerShell skill are a bit new. :)
$i = @()
$a = 0..9
$b = 65..90 | Foreach{[Char]$_}
$i = $a $b
For($d = 0; $d -le $i.count; $d ){
$g = $i[$d]
For($e = 0; $e -le $i.count; $e ){
$h = $i[$e]
For($f = 0; $f -le $i.count; $f ){
$j = $i[$f]
$k = "{0}{1}{2}" -f $g, $h, $j
$k #| Export-Csv -Path .\List.csv -NoTypeInformation -Append
If($k -eq '9ZZ'){
Break
}
}
}
}
Data Output:
000
001
.
.
|
V
009
00A
.
.
00Z
00 <-- I don't get this.
010
Export:
Length
3 <-- I don't get this either.
.
.
|
v
3
Any and all help is appreciated. Thank you in Advanced. ;)
CodePudding user response:
This is a classic off-by-1 error - your loops run from 0 through $i.count (included), which is exactly 1 longer than $i.
Change -le $i.count to -lt $i.count in all 3 loop conditions and it'll work.
You could simplify your code by generating the full range of digits/characters up front a little differently, and then use 3 nested foreach loops instead:
$digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray()
$ranges =
:outerLoop
foreach($a in $digits){
foreach($b in $digits){
foreach($c in $digits){
# save and output new value
($label = "${a}${b}${c}")
# exit the label generation completely if we've reached the desired upper boundary
if($label -eq '9ZZ'){ break outerLoop }
}
}
}
$ranges now contain the correct range of labels from 000 through 9ZZ
CodePudding user response:
I would do it this way, with 3 foreach loops and a labeled break:
$digits = 0..9
$chars = (65..90).ForEach([char])
$dict = $digits $chars
$result = :outer foreach($i in $dict)
{
foreach($x in $dict)
{
foreach($z in $dict)
{
'{0}{1}{2}' -f $i,$x,$z
if($i -eq 9 -and $x -eq 'Z' -and $z -eq 'Z')
{
break outer
}
}
}
}
$result | Export-Csv ...
CodePudding user response:
To complement the helpful existing answers with a generalized solution for producing permutations of characters with a given number of places, using recursive helper function Get-Permutations:
function Get-Permutations {
param(
[Parameter(Mandatory)]
[string] $Chars, # e.g. '0123456789'
[Parameter(Mandatory)]
[uint] $NumPlaces # e.g. 2, to produce '00', '01', ..., '99'
)
switch ($NumPlaces) {
0 { return }
1 { [string[]] $Chars.ToCharArray() }
default {
Get-Permutations -Chars $Chars -NumPlaces ($NumPlaces-1) | ForEach-Object {
foreach ($c in $chars.ToCharArray()) { $_ $c }
}
}
}
}
You'd call it as follows (to get '000', '001', ..., but all the way up to 'ZZZ' - you can post-filter with ... | Where-Object { $_ -le '9ZZ' })
Get-Permutations '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' 3
Note:
- In PowerShell (Core) 7 you can create the string of characters with
-join ('0'..'9' 'A'..'Z') - In Windows PowerShell, where you cannot use
[char]instances with the range operator,.., you can use the following, more concise alternative to your approach:
-join ([char[]] (48..57) [char[]] (65..90)), based on the chars.' code points obtained with, e.g.[int] [char] 'A'
CodePudding user response:
similarly you could cheat since '009' -le '00A'
function inc([string]$s){
[byte[]]$v = [char[]]$s
$radix = $v.Count-1
$carry = $true
while($carry -and $radix -ge 0){
switch( $v[$radix]){
91{$v[$radix] = 48}
58{$v[$radix] = 65; $carry = $false}
default{$carry = $false}
}
$radix--
}
$out = [char[]]$v -join ''
$c = if($carry){'1'}else{''}
return ($c $out)
}
&{for($i = '000'; $i -le '9ZZ'; $i = inc $i){
write-output $i
}} | set-content -Path .\List.csv
