86

I want to iterate over the alphabet like so:

foreach(char c in alphabet)
{
 //do something with letter
}

Is an array of chars the best way to do this? (feels hacky)

Edit: The metric is "least typing to implement whilst still being readable and robust"

weston
  • 54,145
  • 21
  • 145
  • 203
Ben Aston
  • 53,718
  • 65
  • 205
  • 331
  • Anytime you ask a "best" question, you need to give metrics to evaluate against or else everyone is going to throw specific answers out which likely do not apply to your unique situation. – Nick Larsen Feb 05 '10 at 16:42
  • The only thing that may be hacky as you put it is that you are using a foreach loop instead of a standard for loop, but even then its not really hacky. – Woot4Moo Feb 05 '10 at 16:44
  • I was looking for a "neater" way than enumerating over an array of chars. The metric is "least typing to implement whilst still being readable and robust" - Richard's answer is closest to my original thinking (which I couldn't articulate at the time of questioning) – Ben Aston Feb 05 '10 at 16:48
  • See http://stackoverflow.com/questions/314466/generating-an-array-of-letters-in-the-alphabet-in-c http://stackoverflow.com/questions/252662/localization-how-to-map-culture-info-to-a-script-name-or-unicode-character-range – Ben Aston Feb 05 '10 at 17:00

7 Answers7

186

(Assumes ASCII, etc)

for (char c = 'A'; c <= 'Z'; c++)
{
    //do something with letter 
} 

Alternatively, you could split it out to a provider and use an iterator (if you're planning on supporting internationalisation):

public class EnglishAlphabetProvider : IAlphabetProvider
{
    public IEnumerable<char> GetAlphabet()
    {
        for (char c = 'A'; c <= 'Z'; c++)
        {
            yield return c;
        } 
    }
}

IAlphabetProvider provider = new EnglishAlphabetProvider();

foreach (char c in provider.GetAlphabet())
{
    //do something with letter 
} 
Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
  • 5
    Woah...never thought of that. Brilliant! – Bobby Feb 05 '10 at 16:42
  • 15
    If you neeeeed foreach: `Enumerable.Range('a', 'z'-'a' + 1).Select(x=>(char)x)` – Rob Fonseca-Ensor Feb 05 '10 at 16:43
  • @Richard: You just give half of the solution. I like your generic IAlphabetProvider approach, but you need a factory to get the correct provider. Something like: var provider = AlphabetProvider.GetProvider(CultureInfo.CurrentCulture); – Steven Feb 05 '10 at 17:47
  • 8
    It's just sample code, I can't write the entire application in my answer. FYI by having a static method, your solution is coupled to the AlphabetProvider class. – Richard Szalay Feb 06 '10 at 10:29
  • @Rob - you can replace that Select with `Cast`. – Daniel Earwicker Feb 09 '10 at 23:01
  • @Richard Szalay & Rob Fonseca-Ensor: you should add your input to the "Hidden Features of C#" meta-question. Those things are gems! Here's a link to the question: http://stackoverflow.com/questions/9033/hidden-features-of-c – cllpse Feb 09 '10 at 23:05
  • 2
    @Rob - argh! I forgot that normal casts don't work between generic parameters. If you write your own version of `Cast`, you find the compiler won't accept it unless you cast to `object` first. Which makes it a boxing conversion, so you can only get out exactly whatever you put in. So I withdraw my comment. – Daniel Earwicker Feb 10 '10 at 09:33
  • (Although I think it will work in C# 4.0, just installing it now to find out.) – Daniel Earwicker Feb 10 '10 at 09:35
  • Results are mixed... a generic cast via `dynamic` will work. But `Enumerable.Cast` still does an old-style unboxing, so no change there. But it is very easy to write a similar `DynamicCast` extension that says `yield return (TOut)(dynamic)item`, and that works. – Daniel Earwicker Feb 10 '10 at 12:18
  • 3
    It will be really great if you can add the interface's definition `public interface IAlphabetProvider { IList GetAlphabet(); }` as well into your post for clarity as it is a user defined interface. Prima facie it looks as if `IAlphabetProvider` is an already existing interface in .Net framework class library and you have simply implemented it to solve OP's problem. – RBT Aug 03 '17 at 06:05
  • 1
    @RBT - Tbh, the core of my answer was that you can do `for` loops on `char` values. The rest of it was just potential design inspiration if the OP wanted to take it further. – Richard Szalay Aug 03 '17 at 06:30
  • 1
    I understand your point @RichardSzalay. I suggested as it would bring completeness to your post and will be more clearer for the future readers also. For a second one gets lost as from where this interface `IAlphabetProvider` is coming from. – RBT Aug 03 '17 at 06:51
43

Or you could do,

string alphabet = "abcdefghijklmnopqrstuvwxyz";

foreach(char c in alphabet)
{
 //do something with letter
}
Even Mien
  • 44,393
  • 43
  • 115
  • 119
Colin Newell
  • 3,073
  • 1
  • 22
  • 36
  • 2
    With this solution, internationalization is easy: use different letters :) (assuming C#'s foreach char goes by letter rather than 8-bit sequence). If it doesn't, I don't know the best approach for multi-byte characters in C#. – Joey Adams Feb 09 '10 at 23:03
  • @JoeyAdams For internationalization, would you take the hard-coded literal out of the code and get it through the ResourceManager or something? – Jeff B Oct 09 '13 at 21:23
  • 1
    @JoeyAdams [`String.GetEnumerator()`](https://msdn.microsoft.com/en-us/library/system.string.getenumerator%28v=vs.110%29.aspx) goes `char` by char, so you’d only have a partial Unicode code point/surrogate pair if your string contains such characters. So you might want to normalize both your alphabet and the data you are comparing against it and ensure you think in terms of numeric codepoints rather than `char`: https://stackoverflow.com/a/28155130/429091 – binki Jul 05 '17 at 17:58
10
var alphabet = Enumerable.Range(0, 26).Select(i => Convert.ToChar('A' + i));
shankar.siva
  • 189
  • 2
  • 14
5
Enumerable.Range(65, 26).Select(a => new { A = (char)(a) }).ToList().ForEach(c => Console.WriteLine(c.A));
John Boker
  • 82,559
  • 17
  • 97
  • 130
  • 2
    Not much point newing-up an anonymous object to store a single property. And the built-in `foreach` statement is usually clearer for performing an action on each item of a sequence - that's what it's for. – Daniel Earwicker Feb 09 '10 at 23:04
  • To simplify: Enumerable.Range(65, 26).ToList().ForEach(c => Console.WriteLine((char)c)); – Eraph Jun 25 '14 at 12:47
4

Use Enumerable.Range:

Enumerable.Range('A', ('Z' - 'A' + 1)).Select(i => (char)i)
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
2

You could do this:

for(int i = 65; i <= 95; i++)
{
    //use System.Convert.ToChar() f.e. here
    doSomethingWithTheChar(Convert.ToChar(i));
}

Though, not the best way either. Maybe we could help better if we would know the reason for this.

Bobby
  • 11,419
  • 5
  • 44
  • 69
0

I found this:

foreach(char letter in Enumerable.Range(65, 26).ToList().ConvertAll(delegate(int value) { return (char)value; }))
{
//breakpoint here to confirm
}

while randomly reading this blog, and thought it was an interesting way to accomplish the task.

Chris
  • 6,702
  • 8
  • 44
  • 60