Graceful way to create an alphabet array

Answered Graceful way to create an alphabet array

  • Tuesday, October 14, 2008 3:19 AM
     
     
    Just 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
     
     Answered Has Code
    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 AM
    Moderator
     
     Answered
    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 PM
     
     
     Well, it's hard to change long-term programmers habits :)
  • Monday, February 25, 2013 8:12 PM
     
     Proposed

    measure-command { 65..90|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

    measure-command { [int][char]'A'..[int][char]'Z'|foreach-object{ [char]$_ } }

    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.2061

    All 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
     
      Has Code

    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
     
      Has Code

    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:

    1. the character code for "A" is the lowest of the codes corresponding to alphabetic characters;
    2. the character code for "Z" is the highest of the codes corresponding to alphabetic characters; and:
    3. 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
     
      Has Code

    Also

    [char[]]('A'[0]..'Z'[0])

  • Wednesday, March 20, 2013 4:20 PM
     
      Has Code

    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
     
      Has Code

    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
     
      Has Code

    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
     
     
    I see the difference now.  Thanks!
     
     
  • Wednesday, March 20, 2013 10:02 PM
     
      Has Code

    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.