Graceful way to create an alphabet array
-
Tuesday, October 14, 2008 3:19 AMJust curious if there is a graceway to create an array
$alphabet = @("A","B", etc...) without having to type it all in from A-Z.
Thanks,
John
All Replies
-
Tuesday, October 14, 2008 4:35 AM
Try this code:
$alphabet = @() for ([byte]$c = [char]'A'; $c -le [char]'Z'; $c++) { $alphabet += [char]$c } [String]::Join(", ", $alphabet) - Edited by Sergey Popov Tuesday, October 14, 2008 4:36 AM
- Marked As Answer by Chang Yin Tuesday, October 21, 2008 2:06 AM
-
Tuesday, October 14, 2008 11:46 AMModerator
Alternate method:
$alph=@()
65..90|foreach-object{$alph+=[char]$_}
$alph
- Marked As Answer by Chang Yin Tuesday, October 21, 2008 2:06 AM
-
Tuesday, October 14, 2008 12:58 PMWell, it's hard to change long-term programmers habits :)
-
Monday, February 25, 2013 8:12 PM
measure-command { 65..90|foreach-object{ [char]$_ } }
measure-command { [int][char]'A'..[int][char]'Z'|foreach-object{ [char]$_ } }
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 5
Ticks : 55905
TotalDays : 6.47048611111111E-08
TotalHours : 1.55291666666667E-06
TotalMinutes : 9.3175E-05
TotalSeconds : 0.0055905
TotalMilliseconds : 5.5905
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 5
Ticks : 55518
TotalDays : 6.42569444444444E-08
TotalHours : 1.54216666666667E-06
TotalMinutes : 9.253E-05
TotalSeconds : 0.0055518
TotalMilliseconds : 5.5518 measure-command { [char[]]([int][char]'A'..[int][char]'Z') }
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 0
Ticks : 2061
TotalDays : 2.38541666666667E-09
TotalHours : 5.725E-08
TotalMinutes : 3.435E-06
TotalSeconds : 0.0002061
TotalMilliseconds : 0.2061All output is identical. The 3rd option is much more efficient, in case you worry about things like that. In my opinion, its also easier to read.
- Proposed As Answer by Zebulon Griggs Monday, February 25, 2013 9:07 PM
-
Monday, February 25, 2013 9:09 PM
the third option is also one that does not require one to hard-code in an ascii value...
The reason it is the fastest by such a large margin is that it evaluates to a constant literal array expression of the 65..90 variety. the other two pipe 26 values to a foreach.object reference.
Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.
-
Monday, March 18, 2013 12:53 AM
And, FYI, the shortest efficient ways shown can be reduced further by letting PowerShell handle more on its own; either of these work:
[char[]]([char]'A'..[char]'Z')
[char[]](65..90)
-
Monday, March 18, 2013 1:35 AM
You might also want to consider:
[char[]](0..255) -clike '[A-Z]'
if the type of the resulting array needs to be [string[]] rather than [char[]]
[string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "
-
Tuesday, March 19, 2013 9:29 PM
Rob's solution has the added benefit of NOT assuming that:
- the character code for "A" is the lowest of the codes corresponding to alphabetic characters;
- the character code for "Z" is the highest of the codes corresponding to alphabetic characters; and:
- the alpabetic codes are contiguous with no non-alphabetic symbols interspersed.
To those who say: but that is always the case, I say: that is only because windows runs only on ASCII-based computers, not EBCDIC-based ones... ;-)
Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.
-
Tuesday, March 19, 2013 10:18 PM
Also
[char[]]('A'[0]..'Z'[0])
-
Wednesday, March 20, 2013 4:20 PM
Also
[char[]]('A'[0]..'Z'[0])
I count that as mildly less intuitive than Alex's:[char[]]([char]'A'..[char]'Z')
But both methods still assume that the alphabetic symbols appear in the list of codes contiguously and in alphabetical order, whereas Rob's makes no such assumptions. If Windows Powershell is ever ported to EBCDIC-based systems, you will find your code suddenly failing - ;-)
Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.
-
Wednesday, March 20, 2013 4:31 PM
Rob's:
[char[]](0..255) -clike '[A-Z]'
Mine:
[char[]]('A'[0]..'Z'[0])Rob's has a range A-Z
Mine has a range 'A'[0]..'Z'[0]What assumption makes these two different?
-
Wednesday, March 20, 2013 9:34 PM
I believe that, even though you cast to char, the .. notation works with the underlying integer ascii equivalents. I infer that from the error message here:
PS M:\> 'A'..'Z' Cannot convert value "A" to type "System.Int32". Error: "Input string was not in a correct format." At line:1 char:6 + 'A'.. <<<< 'Z' + CategoryInfo : NotSpecified: (:) [], RuntimeException + FullyQualifiedErrorId : RuntimeException PS M:\>
and also this observation:
PS M:\> [int]'A'[0] 65 PS M:\> [int]'A' Cannot convert value "A" to type "System.Int32". Error: "Input string was not in a correct format." At line:1 char:6 + [int] <<<< 'A' + CategoryInfo : NotSpecified: (:) [], RuntimeException + FullyQualifiedErrorId : RuntimeException PS M:\>
Rob's has a range 0..255. The '[A-Z]' is regex-speak for all capital letters of the alphabet, and, I think not, regex-speak for all characters whose codes fall between that of 'A' and 'Z' inclusive.
Perhaps I am wrong, however, if regex works on EBCDIC systems, that "-clike '[A-Z]' would match against the 26 capital letters of the alphabet. I found this info about regex brackets on wikipedia:
A bracket expression. Matches a single character that is contained within the brackets. For example,
[abc]
matches "a", "b", or "c".[a-z]specifies a range which matches any lowercase letter from "a" to "z". These
forms can be mixed:[abcx-z]matches "a", "b", "c", "x", "y", or "z", as does[a-cx-z].I would think, therefore that '[A-Z]' and'[ABCDEFGHIJKLMNOPQRSTUVWXYZ]' would yield the same matches, even where the character codes were not as nicely organized as with ASCII. And here is a reference that I think confirms this to be the case:http://www.nntp.perl.org/group/perl.perl5.porters/2001/02/msg31535.html
Of course, we might have to wait quite a while before we see Windows supported on any system that was not ASCII-based, so it is perhaps a bit of a moot point. But we are all in agreement, I believe, that it would be poor practice to code using the ASCII equivalent codes (i.e. 'A' is 65), even though it will always be thus on an ASCII-based system...
Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.
-
Wednesday, March 20, 2013 9:37 PM
-
Wednesday, March 20, 2013 10:02 PM
Also
[char[]]('A'[0]..'Z'[0])
I count that as mildly less intuitive than Alex's:[char[]]([char]'A'..[char]'Z')
But both methods still assume that the alphabetic symbols appear in the list of codes contiguously and in alphabetical order, whereas Rob's makes no such assumptions. If Windows Powershell is ever ported to EBCDIC-based systems, you will find your code suddenly failing - ;-)
Al Dunbar -- remember to 'mark or propose as answer' or 'vote as helpful' as appropriate.
And of course my solution and the initial ones raise an issue if someone is searching for a way to create all the uppercase letters in any alphabet other than the standard... what? Latin-1?
I actually spent some time looking in the .NET globalization/text-related namespaces to see if I could find enumerations or constants referring to either localized or locale-neutral Unicode code points, since that would be much more elegant. It would be nice if there were System.Char-related enumerations allowing is to pick out the named ranges from the Unicode standard.

